I am trying to implement an abstraction for key-value stores in Rust. Therefore I have two traits: The IStorageSystem
which is partitioned into multiple IStore
s that provide the actual key-value pairs. If a store is opened, the internal tree-map should be locked until the opened store goes out of scope. Further the whole access should be thread-safe:
use std::collections::BTreeMap;
use std::sync::{Arc, RwLock, RwLockReadGuard};
pub type Bytes = Vec<u8>;
pub trait IStorageSystem {
fn open_read<'sys>(&'sys mut self, name: &str) -> Box<IReadOnlyStore<'sys> + 'sys>;
}
pub trait IReadOnlyStore<'sys> {
fn get(&'sys self, key: &Bytes) -> Option<&'sys Bytes>;
}
type StoreData = BTreeMap<Bytes, Bytes>;
struct InMemoryStorageSystem {
stores: BTreeMap<String, Arc<RwLock<StoreData>>>,
}
impl InMemoryStorageSystem {
pub fn new() -> InMemoryStorageSystem {
InMemoryStorageSystem {
stores: BTreeMap::new(),
}
}
}
impl IStorageSystem for InMemoryStorageSystem {
fn open_read<'sys>(&'sys mut self, name: &str) -> Box<IReadOnlyStore<'sys> + 'sys> {
let store_data = self.stores.entry(name.into())
.or_insert(Arc::new(RwLock::new(StoreData::new())));
Box::new(ReadOnlyInMemoryStore::new(store_data))
}
}
struct ReadOnlyInMemoryStore<'sys> {
data: RwLockReadGuard<'sys, StoreData>,
}
impl<'sys> ReadOnlyInMemoryStore<'sys> {
fn new(data: &'sys Arc<RwLock<StoreData>>) -> ReadOnlyInMemoryStore<'sys> {
let locked_data = data.read().unwrap();
ReadOnlyInMemoryStore {
data: locked_data,
}
}
}
impl<'sys> IReadOnlyStore<'sys> for ReadOnlyInMemoryStore<'sys> {
fn get(&'sys self, key: &Bytes) -> Option<&'sys Bytes> {
self.data.get(key)
}
}
fn main() {
let mut storage = InMemoryStorageSystem::new();
let store = storage.open_read("values");
let key = String::from("dummy").into_bytes();
let value = store.get(&key);
match value {
Some(ref val) => println!("Got {:?}", value),
None => println!("Nothing found"),
}
}
When I try to compile this code I get the following error:
error[E0597]: `*store` does not live long enough
--> src/main.rs:69:1
|
64 | let value = store.get(&key);
| ----- borrow occurs here
...
69 | }
| ^ `*store` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
How do I fix this? As far as I see, this should be working because all lifetimes are bound to the storage system which is created first and thus should be dropped last.