1use crate::{error, Change, ColumnId, Database, Transaction};
21use parking_lot::RwLock;
22use std::collections::{hash_map::Entry, HashMap};
23
24#[derive(Default)]
25pub struct MemDb(RwLock<HashMap<ColumnId, HashMap<Vec<u8>, (u32, Vec<u8>)>>>);
27
28impl<H> Database<H> for MemDb
29where
30 H: Clone + AsRef<[u8]>,
31{
32 fn commit(&self, transaction: Transaction<H>) -> error::Result<()> {
33 let mut s = self.0.write();
34 for change in transaction.0.into_iter() {
35 match change {
36 Change::Set(col, key, value) => {
37 s.entry(col).or_default().insert(key, (1, value));
38 },
39 Change::Remove(col, key) => {
40 s.entry(col).or_default().remove(&key);
41 },
42 Change::Store(col, hash, value) => {
43 s.entry(col)
44 .or_default()
45 .entry(hash.as_ref().to_vec())
46 .and_modify(|(c, _)| *c += 1)
47 .or_insert_with(|| (1, value));
48 },
49 Change::Reference(col, hash) => {
50 if let Entry::Occupied(mut entry) =
51 s.entry(col).or_default().entry(hash.as_ref().to_vec())
52 {
53 entry.get_mut().0 += 1;
54 }
55 },
56 Change::Release(col, hash) => {
57 if let Entry::Occupied(mut entry) =
58 s.entry(col).or_default().entry(hash.as_ref().to_vec())
59 {
60 entry.get_mut().0 -= 1;
61 if entry.get().0 == 0 {
62 entry.remove();
63 }
64 }
65 },
66 }
67 }
68
69 Ok(())
70 }
71
72 fn get(&self, col: ColumnId, key: &[u8]) -> Option<Vec<u8>> {
73 let s = self.0.read();
74 s.get(&col).and_then(|c| c.get(key).map(|(_, v)| v.clone()))
75 }
76}
77
78impl MemDb {
79 pub fn new() -> Self {
81 MemDb::default()
82 }
83
84 pub fn count(&self, col: ColumnId) -> usize {
86 let s = self.0.read();
87 s.get(&col).map(|c| c.len()).unwrap_or(0)
88 }
89}