make Manager consumable (#21, r=ncalexan)

without.crypto
Myk Melez 6 years ago committed by GitHub
parent 231533dd70
commit 9f0dfdc8a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.toml
  2. 3
      src/lib.rs
  3. 23
      src/manager.rs
  4. 40
      tests/manager.rs

@ -14,6 +14,7 @@ backtrace = ["failure/backtrace", "failure/std"]
[dependencies]
arrayref = "0.3"
bincode = "0.9"
lazy_static = "1.0"
lmdb = "0.7"
ordered-float = "0.5"
uuid = "0.5"

@ -12,6 +12,7 @@
#[macro_use] extern crate arrayref;
#[macro_use] extern crate failure;
#[macro_use] extern crate lazy_static;
extern crate bincode;
extern crate lmdb;
@ -48,7 +49,7 @@ pub use integer::{
};
pub use manager::{
Manager,
Manager
};
pub use readwrite::{

@ -27,7 +27,6 @@ use std::path::{
use std::sync::{
Arc,
Mutex,
RwLock,
};
@ -39,22 +38,32 @@ use ::Rkv;
/// A process is only permitted to have one open handle to each database. This manager
/// exists to enforce that constraint: don't open databases directly.
lazy_static! {
static ref MANAGER: RwLock<Manager> = {
RwLock::new(Manager::new())
};
}
pub struct Manager {
stores: Mutex<BTreeMap<PathBuf, Arc<RwLock<Rkv>>>>,
stores: BTreeMap<PathBuf, Arc<RwLock<Rkv>>>,
}
impl Manager {
fn new() -> Manager {
Manager {
stores: Mutex::new(Default::default()),
stores: Default::default(),
}
}
pub fn singleton() -> &'static RwLock<Manager> {
&*MANAGER
}
/// Return the open store at `path`, returning `None` if it has not already been opened.
pub fn get<'p, P>(&self, path: P) -> Result<Option<Arc<RwLock<Rkv>>>, ::std::io::Error>
where P: Into<&'p Path> {
let canonical = path.into().canonicalize()?;
Ok(self.stores.lock().unwrap().get(&canonical).cloned())
Ok(self.stores.get(&canonical).cloned())
}
/// Return the open store at `path`, or create it by calling `f`.
@ -62,8 +71,7 @@ impl Manager {
where F: FnOnce(&Path) -> Result<Rkv, StoreError>,
P: Into<&'p Path> {
let canonical = path.into().canonicalize()?;
let mut map = self.stores.lock().unwrap();
Ok(match map.entry(canonical) {
Ok(match self.stores.entry(canonical) {
Entry::Occupied(e) => e.get().clone(),
Entry::Vacant(e) => {
let k = Arc::new(RwLock::new(f(e.key().as_path())?));
@ -78,8 +86,7 @@ impl Manager {
where F: FnOnce(&Path, c_uint) -> Result<Rkv, StoreError>,
P: Into<&'p Path> {
let canonical = path.into().canonicalize()?;
let mut map = self.stores.lock().unwrap();
Ok(match map.entry(canonical) {
Ok(match self.stores.entry(canonical) {
Entry::Occupied(e) => e.get().clone(),
Entry::Vacant(e) => {
let k = Arc::new(RwLock::new(f(e.key().as_path(), capacity)?));

@ -0,0 +1,40 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
extern crate rkv;
extern crate tempdir;
use rkv::{
Manager,
Rkv,
};
use self::tempdir::TempDir;
use std::fs;
use std::sync::{
Arc,
};
#[test]
// Identical to the same-named unit test, but this one confirms that it works
// via the public MANAGER singleton.
fn test_same() {
let root = TempDir::new("test_same_singleton").expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let p = root.path();
assert!(Manager::singleton().read().unwrap().get(p).expect("success").is_none());
let created_arc = Manager::singleton().write().unwrap().get_or_create(p, Rkv::new).expect("created");
let fetched_arc = Manager::singleton().read().unwrap().get(p).expect("success").expect("existed");
assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}
Loading…
Cancel
Save