Share blockchain state using MemoryDB
// limitations under the License.
//! An implementation of `MemoryDB` database.
+use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::clone::Clone;
use std::collections::btree_map::{BTreeMap, Range};
use std::iter::Peekable;
@@ -24,18 +25,19 @@ use super::{Database, Snapshot, Patch, Change, Iterator, Iter, Result};
/// It's mainly used for testing and not designed to be efficient.
#[derive(Default, Clone, Debug)]
pub struct MemoryDB {
- map: BTreeMap<Vec<u8>, Vec<u8>>,
+ map: Arc<RwLock<BTreeMap<Vec<u8>, Vec<u8>>>>,
}
/// An iterator over the entries of a `MemoryDB`.
struct MemoryDBIter<'a> {
iter: Peekable<Range<'a, Vec<u8>, Vec<u8>>>,
+ _guard: RwLockReadGuard<'a, BTreeMap<Vec<u8>, Vec<u8>>>
}
impl MemoryDB {
/// Creates a new, empty database.
pub fn new() -> MemoryDB {
- MemoryDB { map: BTreeMap::new() }
+ MemoryDB { map: Arc::new(RwLock::new(BTreeMap::new())) }
}
}
@@ -52,10 +54,10 @@ impl Database for MemoryDB {
for (key, change) in patch {
match change {
Change::Put(value) => {
- self.map.insert(key, value);
+ self.map.write().unwrap().insert(key, value);
}
Change::Delete => {
- self.map.remove(&key);
+ self.map.write().unwrap().remove(&key);
}
}
}
@@ -65,18 +67,22 @@ impl Database for MemoryDB {
impl Snapshot for MemoryDB {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
- self.map.get(key).cloned()
+ self.map.read().unwrap().get(key).cloned()
}
fn contains(&self, key: &[u8]) -> bool {
- self.map.contains_key(key)
+ self.map.read().unwrap().contains_key(key)
}
fn iter<'a>(&'a self, from: &[u8]) -> Iter<'a> {
- use std::collections::Bound::*;
+ use std::collections::Bound::{Included, Unbounded};
+ use std::mem::transmute;
let range = (Included(from), Unbounded);
+ let guard = self.map.read().unwrap();
+
Box::new(MemoryDBIter {
- iter: self.map.range::<[u8], _>(range).peekable(),
+ iter: unsafe { transmute(guard.range::<[u8], _>(range).peekable()) },
+ _guard: guard
})
}
}
