diff --git a/lib/src/store/memory.rs b/lib/src/store/memory.rs index 9eff3d43..34490901 100644 --- a/lib/src/store/memory.rs +++ b/lib/src/store/memory.rs @@ -1,14 +1,12 @@ -use failure::Backtrace; use std::collections::BTreeMap; use std::collections::BTreeSet; -use std::str::FromStr; -use std::sync::PoisonError; use std::sync::RwLock; use std::sync::RwLockReadGuard; use std::sync::RwLockWriteGuard; use store::encoded::*; use store::numeric_encoder::*; use url::Url; +use utils::MutexPoisonError; use Result; /// Memory based implementation of the `rudf::model::Dataset` trait. @@ -49,20 +47,16 @@ pub type MemoryDataset = StoreDataset; pub type MemoryGraph = StoreDefaultGraph; pub struct MemoryStore { - id2str: RwLock>, - str2id: RwLock>, + string_store: MemoryStringStore, graph_indexes: RwLock>, } impl Default for MemoryStore { fn default() -> Self { - let new = Self { - id2str: RwLock::default(), - str2id: RwLock::default(), + Self { + string_store: MemoryStringStore::default(), graph_indexes: RwLock::default(), - }; - new.set_first_strings().unwrap(); - new + } } } @@ -75,32 +69,15 @@ struct MemoryGraphIndexes { impl StringStore for MemoryStore { fn insert_str(&self, value: &str) -> Result { - let mut id2str = self.id2str.write().map_err(MemoryStorePoisonError::from)?; - let mut str2id = self.str2id.write().map_err(MemoryStorePoisonError::from)?; - let id = str2id.entry(value.to_string()).or_insert_with(|| { - let id = id2str.len() as u64; - id2str.push(value.to_string()); - id - }); - Ok(*id) + self.string_store.insert_str(value) } fn get_str(&self, id: u64) -> Result { - let id2str = self.id2str.read().map_err(MemoryStorePoisonError::from)?; - if id2str.len() as u64 <= id { - Err(format_err!("value not found in the dictionary")) - } else { - Ok(id2str[id as usize].to_owned()) - } + self.string_store.get_str(id) } fn get_url(&self, id: u64) -> Result { - let id2str = self.id2str.read().map_err(MemoryStorePoisonError::from)?; - if id2str.len() as u64 <= id { - Err(format_err!("value not found in the dictionary")) - } else { - Ok(Url::from_str(&id2str[id as usize])?) - } + self.string_store.get_url(id) } } @@ -505,32 +482,12 @@ impl EncodedQuadsStore for MemoryStore { impl MemoryStore { fn graph_indexes(&self) -> Result>> { - Ok(self - .graph_indexes - .read() - .map_err(MemoryStorePoisonError::from)?) + Ok(self.graph_indexes.read().map_err(MutexPoisonError::from)?) } fn graph_indexes_mut( &self, ) -> Result>> { - Ok(self - .graph_indexes - .write() - .map_err(MemoryStorePoisonError::from)?) - } -} - -#[derive(Debug, Fail)] -#[fail(display = "MemoryStore Mutex was poisoned")] -pub struct MemoryStorePoisonError { - backtrace: Backtrace, -} - -impl From> for MemoryStorePoisonError { - fn from(_: PoisonError) -> Self { - Self { - backtrace: Backtrace::new(), - } + Ok(self.graph_indexes.write().map_err(MutexPoisonError::from)?) } } diff --git a/lib/src/store/numeric_encoder.rs b/lib/src/store/numeric_encoder.rs index 8585f864..4ccedd1b 100644 --- a/lib/src/store/numeric_encoder.rs +++ b/lib/src/store/numeric_encoder.rs @@ -7,10 +7,14 @@ use model::vocab::xsd; use model::*; use ordered_float::OrderedFloat; use rust_decimal::Decimal; +use std::collections::BTreeMap; use std::io::Read; use std::io::Write; use std::str; +use std::str::FromStr; +use std::sync::RwLock; use url::Url; +use utils::MutexPoisonError; use uuid::Uuid; use Result; @@ -50,6 +54,53 @@ pub trait StringStore { } } +pub struct MemoryStringStore { + id2str: RwLock>, + str2id: RwLock>, +} + +impl Default for MemoryStringStore { + fn default() -> Self { + let new = Self { + id2str: RwLock::default(), + str2id: RwLock::default(), + }; + new.set_first_strings().unwrap(); + new + } +} + +impl StringStore for MemoryStringStore { + fn insert_str(&self, value: &str) -> Result { + let mut id2str = self.id2str.write().map_err(MutexPoisonError::from)?; + let mut str2id = self.str2id.write().map_err(MutexPoisonError::from)?; + let id = str2id.entry(value.to_string()).or_insert_with(|| { + let id = id2str.len() as u64; + id2str.push(value.to_string()); + id + }); + Ok(*id) + } + + fn get_str(&self, id: u64) -> Result { + let id2str = self.id2str.read().map_err(MutexPoisonError::from)?; + if id2str.len() as u64 <= id { + Err(format_err!("value not found in the dictionary")) + } else { + Ok(id2str[id as usize].to_owned()) + } + } + + fn get_url(&self, id: u64) -> Result { + let id2str = self.id2str.read().map_err(MutexPoisonError::from)?; + if id2str.len() as u64 <= id { + Err(format_err!("value not found in the dictionary")) + } else { + Ok(Url::from_str(&id2str[id as usize])?) + } + } +} + const TYPE_DEFAULT_GRAPH_ID: u8 = 0; const TYPE_NAMED_NODE_ID: u8 = 1; const TYPE_BLANK_NODE_ID: u8 = 2; @@ -652,48 +703,6 @@ impl Default for Encoder { } mod test { - use std::cell::RefCell; - use std::collections::BTreeMap; - use std::str::FromStr; - use store::numeric_encoder::*; - - #[derive(Default)] - struct MemoryStringStore { - id2str: RefCell>, - str2id: RefCell>, - } - - impl StringStore for MemoryStringStore { - fn insert_str(&self, value: &str) -> Result { - let mut str2id = self.str2id.borrow_mut(); - let mut id2str = self.id2str.borrow_mut(); - let id = str2id.entry(value.to_string()).or_insert_with(|| { - let id = id2str.len() as u64; - id2str.push(value.to_string()); - id - }); - Ok(*id) - } - - fn get_str(&self, id: u64) -> Result { - let id2str = self.id2str.borrow(); - if id2str.len() as u64 <= id { - Err(format_err!("value not found in the dictionary")) - } else { - Ok(id2str[id as usize].to_owned()) - } - } - - fn get_url(&self, id: u64) -> Result { - let id2str = self.id2str.borrow(); - if id2str.len() as u64 <= id { - Err(format_err!("value not found in the dictionary")) - } else { - Ok(Url::from_str(&id2str[id as usize])?) - } - } - } - #[test] fn test_encoding() { use model::*; diff --git a/lib/src/store/rocksdb.rs b/lib/src/store/rocksdb.rs index f0d97d34..e7730f93 100644 --- a/lib/src/store/rocksdb.rs +++ b/lib/src/store/rocksdb.rs @@ -1,6 +1,5 @@ use byteorder::ByteOrder; use byteorder::LittleEndian; -use failure::Backtrace; use rocksdb::ColumnFamily; use rocksdb::DBRawIterator; use rocksdb::Options; @@ -12,11 +11,11 @@ use std::path::Path; use std::str; use std::str::FromStr; use std::sync::Mutex; -use std::sync::PoisonError; use store::encoded::EncodedQuadsStore; use store::encoded::StoreDataset; use store::numeric_encoder::*; use url::Url; +use utils::MutexPoisonError; use Result; /// `rudf::model::Dataset` trait implementation based on the [RocksDB](https://rocksdb.org/) key-value store @@ -94,7 +93,7 @@ impl StringStore for RocksDbStore { let id = self .str_id_counter .lock() - .map_err(RocksDBCounterMutexPoisonError::from)? + .map_err(MutexPoisonError::from)? .get_and_increment(&self.db)? as u64; let id_bytes = to_bytes(id); let mut batch = WriteBatch::default(); @@ -549,20 +548,6 @@ fn to_bytes(int: u64) -> [u8; 8] { buf } -#[derive(Debug, Fail)] -#[fail(display = "RocksDBStore Mutex was poisoned")] -pub struct RocksDBCounterMutexPoisonError { - backtrace: Backtrace, -} - -impl From> for RocksDBCounterMutexPoisonError { - fn from(_: PoisonError) -> Self { - Self { - backtrace: Backtrace::new(), - } - } -} - // TODO: very bad but I believe it is fine #[derive(Clone, Copy)] struct SendColumnFamily(ColumnFamily); diff --git a/lib/src/utils.rs b/lib/src/utils.rs index fafa5d92..9d994263 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -1,3 +1,6 @@ +use failure::Backtrace; +use std::sync::PoisonError; + pub trait Escaper { fn escape(&self) -> String; } @@ -109,3 +112,17 @@ impl StaticSliceMap { None } } + +#[derive(Debug, Fail)] +#[fail(display = "Mutex Mutex was poisoned")] +pub struct MutexPoisonError { + backtrace: Backtrace, +} + +impl From> for MutexPoisonError { + fn from(_: PoisonError) -> Self { + Self { + backtrace: Backtrace::new(), + } + } +}