trie_test/database/
mod.rs

1mod memory;
2
3use super::{SecureTrie, FixedTrie, FixedSecureTrie, Trie};
4
5pub use self::memory::{MemoryDatabase, MemoryDatabaseGuard};
6
7use bigint::H256;
8use rlp;
9use std::collections::HashMap;
10use std::cell::RefCell;
11
12pub trait Database<'a> {
13    type Guard: DatabaseGuard + 'a;
14
15    fn create_guard(&'a self) -> Self::Guard;
16    fn create_trie(&'a self, root: H256) -> Trie<Self::Guard> {
17        Trie::existing(self.create_guard(), root)
18    }
19    fn create_empty(&'a self) -> Trie<Self::Guard> {
20        self.create_trie(empty_trie_hash!())
21    }
22    fn create_secure_trie(&'a self, root: H256) -> SecureTrie<Self::Guard> {
23        SecureTrie::new(self.create_trie(root))
24    }
25    fn create_secure_empty(&'a self) -> SecureTrie<Self::Guard> {
26        SecureTrie::new(self.create_empty())
27    }
28    fn create_fixed_trie<K: rlp::Encodable + rlp::Decodable, V: rlp::Encodable + rlp::Decodable>(&'a self, root: H256) -> FixedTrie<Self::Guard, K, V> {
29        FixedTrie::new(self.create_trie(root))
30    }
31    fn create_fixed_empty<K: rlp::Encodable + rlp::Decodable, V: rlp::Encodable + rlp::Decodable>(&'a self) -> FixedTrie<Self::Guard, K, V> {
32        FixedTrie::new(self.create_empty())
33    }
34    fn create_fixed_secure_trie<K: AsRef<[u8]>, V: rlp::Encodable + rlp::Decodable>(&'a self, root: H256) -> FixedSecureTrie<Self::Guard, K, V> {
35        FixedSecureTrie::new(self.create_secure_trie(root))
36    }
37    fn create_fixed_secure_empty<K: AsRef<[u8]>, V: rlp::Encodable + rlp::Decodable>(&'a self) -> FixedSecureTrie<Self::Guard, K, V> {
38        FixedSecureTrie::new(self.create_secure_empty())
39    }
40}
41
42pub trait DatabaseOwned: for<'a> Database<'a> {}
43impl<T> DatabaseOwned for T where T: for<'a> Database<'a> {}
44
45pub trait DatabaseGuard {
46    fn get(&self, hash: H256) -> Option<Vec<u8>>;
47    fn set(&mut self, hash: H256, value: Vec<u8>);
48}
49
50impl DatabaseGuard for HashMap<H256, Vec<u8>> {
51    fn get<'a>(&'a self, hash: H256) -> Option<Vec<u8>> {
52        self.get(&hash).map(|v| v.clone())
53    }
54
55    fn set<'a>(&'a mut self, hash: H256, value: Vec<u8>) {
56        self.insert(hash, value);
57    }
58}
59
60pub struct Change<'a, D: 'a> {
61    database: &'a D,
62    cache: RefCell<HashMap<H256, Vec<u8>>>,
63
64    inserted: Vec<H256>,
65    freed: Vec<H256>,
66}
67
68impl<'a, D: DatabaseGuard> Change<'a, D> {
69    pub fn new(database: &'a D) -> Self {
70        Self {
71            database,
72            cache: RefCell::new(HashMap::new()),
73
74            inserted: Vec::new(),
75            freed: Vec::new(),
76        }
77    }
78
79    pub fn get<'b>(&'b self, hash: H256) -> Option<Vec<u8>> {
80        if self.cache.borrow().contains_key(&hash) {
81            self.cache.borrow().get(&hash).map(|v| v.clone())
82        } else {
83            let val = self.database.get(hash);
84            if val.is_some() {
85                self.cache.borrow_mut().insert(hash, val.clone().unwrap());
86            }
87            val
88        }
89    }
90
91    pub fn set<'b, 'c>(&'b mut self, hash: H256, value: Vec<u8>) {
92        self.cache.borrow_mut().insert(hash, value);
93        self.inserted.push(hash);
94    }
95
96    pub fn free<'b>(&'b mut self, hash: H256) {
97        self.freed.push(hash);
98    }
99
100    pub fn inserted<'b>(&'b self) -> &'b [H256] {
101        self.inserted.as_ref()
102    }
103
104    pub fn freed<'b>(&'b self) -> &'b [H256] {
105        self.freed.as_ref()
106    }
107}
108
109impl<'a, D: DatabaseGuard> From<Change<'a, D>> for ChangeSet {
110    fn from(val: Change<'a, D>) -> Self {
111        ChangeSet {
112            cache: val.cache,
113            inserted: val.inserted,
114            freed: val.freed,
115        }
116    }
117}
118
119pub struct ChangeSet {
120    cache: RefCell<HashMap<H256, Vec<u8>>>,
121
122    inserted: Vec<H256>,
123    freed: Vec<H256>,
124}
125
126impl ChangeSet {
127    pub fn drain<D: DatabaseGuard>(self, database: &mut D, nofree: bool) {
128        if !nofree { unimplemented!() }
129
130        for h in self.inserted {
131            database.set(h, self.cache.borrow().get(&h).unwrap().clone())
132        }
133    }
134}