diff --git a/ethcore/account-state/src/backend.rs b/ethcore/account-state/src/backend.rs index 5aa675ff929..b51705235e0 100644 --- a/ethcore/account-state/src/backend.rs +++ b/ethcore/account-state/src/backend.rs @@ -21,7 +21,7 @@ //! should become general over time to the point where not even a //! merkle trie is strictly necessary. -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::sync::Arc; use ethereum_types::{Address, H256}; @@ -29,7 +29,6 @@ use hash_db::{AsHashDB, EMPTY_PREFIX, HashDB, Prefix}; use kvdb::DBValue; use memory_db::{HashKey, MemoryDB}; use parking_lot::Mutex; -use journaldb::AsKeyedHashDB; use keccak_hasher::KeccakHasher; use crate::account::Account; @@ -90,10 +89,6 @@ impl ProofCheck { } } -impl journaldb::KeyedHashDB for ProofCheck { - fn keys(&self) -> HashMap { self.0.keys() } -} - impl HashDB for ProofCheck { fn get(&self, key: &H256, prefix: Prefix) -> Option { self.0.get(key, prefix) @@ -146,23 +141,11 @@ pub struct Proving { proof: Mutex>, } -impl AsKeyedHashDB for Proving { - fn as_keyed_hash_db(&self) -> &dyn journaldb::KeyedHashDB { self } -} - impl + Send + Sync> AsHashDB for Proving { fn as_hash_db(&self) -> &dyn HashDB { self } fn as_hash_db_mut(&mut self) -> &mut dyn HashDB { self } } -impl journaldb::KeyedHashDB for Proving { - fn keys(&self) -> HashMap { - let mut keys = self.base.as_keyed_hash_db().keys(); - keys.extend(self.changed.keys()); - keys - } -} - impl + Send + Sync> HashDB for Proving { fn get(&self, key: &H256, prefix: Prefix) -> Option { match self.base.as_hash_db().get(key, prefix) { diff --git a/util/journaldb/Cargo.toml b/util/journaldb/Cargo.toml index eada2b21311..051a519aeb8 100644 --- a/util/journaldb/Cargo.toml +++ b/util/journaldb/Cargo.toml @@ -4,12 +4,13 @@ version = "0.2.0" authors = ["Parity Technologies "] description = "A `HashDB` which can manage a short-term journal potentially containing many forks of mutually exclusive actions" license = "GPL3" +edition = "2018" [dependencies] parity-bytes = "0.1" ethereum-types = "0.6.0" hash-db = "0.12.4" -parity-util-mem = "0.1" +malloc_size_of = { version = "0.1", package = "parity-util-mem" } keccak-hasher = { path = "../keccak-hasher" } kvdb = "0.1" log = "0.4" diff --git a/util/journaldb/src/archivedb.rs b/util/journaldb/src/archivedb.rs index ed357d80d6b..e0bb6cc6212 100644 --- a/util/journaldb/src/archivedb.rs +++ b/util/journaldb/src/archivedb.rs @@ -16,20 +16,24 @@ //! Disk-backed `HashDB` implementation. -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::io; -use std::sync::Arc; +use std::{ + collections::{HashMap, hash_map::Entry}, + io, + sync::Arc, +}; -use bytes::Bytes; use ethereum_types::H256; -use parity_util_mem::MallocSizeOfExt; use hash_db::{HashDB, Prefix}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; +use malloc_size_of::MallocSizeOfExt; +use parity_bytes::Bytes; use rlp::{encode, decode}; -use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_key_already_exists, error_negatively_reference_hash}; -use traits::JournalDB; + +use crate::{ + DB_PREFIX_LEN, LATEST_ERA_KEY, error_key_already_exists, error_negatively_reference_hash, + JournalDB, new_memory_db +}; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay /// and latent-removal semantics. @@ -52,7 +56,7 @@ impl ArchiveDB { .expect("Low-level database error.") .map(|val| decode::(&val).expect("decoding db value failed")); ArchiveDB { - overlay: ::new_memory_db(), + overlay: new_memory_db(), backing, latest_era, column, @@ -92,28 +96,7 @@ impl HashDB for ArchiveDB { } } -impl ::traits::KeyedHashDB for ArchiveDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } -} - impl JournalDB for ArchiveDB { - fn boxed_clone(&self) -> Box { Box::new(ArchiveDB { overlay: self.overlay.clone(), @@ -200,15 +183,33 @@ impl JournalDB for ArchiveDB { fn consolidate(&mut self, with: super::MemoryDB) { self.overlay.consolidate(with); } + + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } } #[cfg(test)] mod tests { - - use keccak::keccak; + use keccak_hash::keccak; use hash_db::{HashDB, EMPTY_PREFIX}; use super::*; - use {kvdb_memorydb, JournalDB}; + use kvdb_memorydb; + use crate::{JournalDB, inject_batch, commit_batch}; #[test] fn insert_same_in_fork() { @@ -216,18 +217,18 @@ mod tests { let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); - jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); - jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); jdb.remove(&x, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); - jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); - jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); assert!(jdb.contains(&x, EMPTY_PREFIX)); } @@ -237,16 +238,16 @@ mod tests { // history is 3 let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); jdb.remove(&h, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); } @@ -255,13 +256,13 @@ mod tests { fn multiple_owed_removal_not_allowed() { let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); jdb.remove(&h, EMPTY_PREFIX); jdb.remove(&h, EMPTY_PREFIX); // commit_batch would call journal_under(), // and we don't allow multiple owned removals. - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); } #[test] @@ -271,29 +272,29 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.remove(&baz, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); } #[test] @@ -303,22 +304,22 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -328,16 +329,16 @@ mod tests { let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); jdb.insert(EMPTY_PREFIX, b"foo"); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -345,16 +346,16 @@ mod tests { fn fork_same_key() { // history is 1 let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -368,21 +369,21 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar")); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); foo }; { let mut jdb = ArchiveDB::new(shared_db.clone(), None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); } { let mut jdb = ArchiveDB::new(shared_db, None); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); } } @@ -394,24 +395,24 @@ mod tests { let mut jdb = ArchiveDB::new(shared_db.clone(), None); // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); // foo is ancient history. jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); foo }; { let mut jdb = ArchiveDB::new(shared_db, None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); - jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); } } @@ -423,19 +424,19 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); (foo, bar, baz) }; { let mut jdb = ArchiveDB::new(shared_db, None); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } } @@ -447,7 +448,7 @@ mod tests { let key = { let mut jdb = ArchiveDB::new(shared_db.clone(), None); let key = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); key }; @@ -462,11 +463,11 @@ mod tests { fn inject() { let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); let key = jdb.insert(EMPTY_PREFIX, b"dog"); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog")); jdb.remove(&key, EMPTY_PREFIX); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert!(jdb.get(&key, EMPTY_PREFIX).is_none()); } diff --git a/util/journaldb/src/as_hash_db_impls.rs b/util/journaldb/src/as_hash_db_impls.rs index cafed203261..eae3c1f8a0a 100644 --- a/util/journaldb/src/as_hash_db_impls.rs +++ b/util/journaldb/src/as_hash_db_impls.rs @@ -17,13 +17,16 @@ //! Impls of the `AsHashDB` upcast trait for all different variants of DB use hash_db::{HashDB, AsHashDB}; use keccak_hasher::KeccakHasher; -use archivedb::ArchiveDB; -use earlymergedb::EarlyMergeDB; -use overlayrecentdb::OverlayRecentDB; -use refcounteddb::RefCountedDB; -use overlaydb::OverlayDB; + use kvdb::DBValue; -use crate::{KeyedHashDB, AsKeyedHashDB}; + +use crate::{ + archivedb::ArchiveDB, + earlymergedb::EarlyMergeDB, + overlayrecentdb::OverlayRecentDB, + refcounteddb::RefCountedDB, + overlaydb::OverlayDB, +}; impl AsHashDB for ArchiveDB { fn as_hash_db(&self) -> &dyn HashDB { self } @@ -49,23 +52,3 @@ impl AsHashDB for OverlayDB { fn as_hash_db(&self) -> &dyn HashDB { self } fn as_hash_db_mut(&mut self) -> &mut dyn HashDB { self } } - -impl AsKeyedHashDB for ArchiveDB { - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self } -} - -impl AsKeyedHashDB for EarlyMergeDB { - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self } -} - -impl AsKeyedHashDB for OverlayRecentDB { - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self } -} - -impl AsKeyedHashDB for RefCountedDB { - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self } -} - -impl AsKeyedHashDB for OverlayDB { - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB { self } -} diff --git a/util/journaldb/src/earlymergedb.rs b/util/journaldb/src/earlymergedb.rs index 0679bd5908d..9589212b9ef 100644 --- a/util/journaldb/src/earlymergedb.rs +++ b/util/journaldb/src/earlymergedb.rs @@ -16,22 +16,27 @@ //! Disk-backed `HashDB` implementation. -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::io; -use std::sync::Arc; +use std::{ + collections::{HashMap, hash_map::Entry}, + io, + sync::Arc, +}; -use bytes::Bytes; use ethereum_types::H256; use hash_db::{HashDB, Prefix}; -use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; +use log::{trace, warn}; +use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops}; +use parity_bytes::Bytes; use parking_lot::RwLock; use rlp::{encode, decode}; -use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_negatively_reference_hash, error_key_already_exists}; -use super::traits::JournalDB; -use util::{DatabaseKey, DatabaseValueView, DatabaseValueRef}; + +use crate::{ + DB_PREFIX_LEN, LATEST_ERA_KEY, error_negatively_reference_hash, error_key_already_exists, + JournalDB, new_memory_db, + util::{DatabaseKey, DatabaseValueView, DatabaseValueRef}, +}; #[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] struct RefInfo { @@ -115,7 +120,7 @@ impl EarlyMergeDB { let (latest_era, refs) = EarlyMergeDB::read_refs(&*backing, col); let refs = Some(Arc::new(RwLock::new(refs))); EarlyMergeDB { - overlay: ::new_memory_db(), + overlay: new_memory_db(), backing: backing, refs: refs, latest_era: latest_era, @@ -311,26 +316,6 @@ impl HashDB for EarlyMergeDB { } } -impl ::traits::KeyedHashDB for EarlyMergeDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } -} - impl JournalDB for EarlyMergeDB { fn boxed_clone(&self) -> Box { Box::new(EarlyMergeDB { @@ -519,16 +504,33 @@ impl JournalDB for EarlyMergeDB { fn consolidate(&mut self, with: super::MemoryDB) { self.overlay.consolidate(with); } + + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } } #[cfg(test)] mod tests { - - use keccak::keccak; + use keccak_hash::keccak; use hash_db::{HashDB, EMPTY_PREFIX}; use super::*; - use super::super::traits::JournalDB; use kvdb_memorydb; + use crate::{inject_batch, commit_batch}; #[test] fn insert_same_in_fork() { @@ -536,25 +538,25 @@ mod tests { let mut jdb = new_db(); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&x, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&x, EMPTY_PREFIX)); @@ -564,17 +566,17 @@ mod tests { fn insert_older_era() { let mut jdb = new_db(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0a"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(0, &keccak(b"0b"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -585,20 +587,20 @@ mod tests { // history is 3 let mut jdb = new_db(); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); jdb.remove(&h, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&h, EMPTY_PREFIX)); } @@ -610,7 +612,7 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -618,7 +620,7 @@ mod tests { jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -626,20 +628,20 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.remove(&baz, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); @@ -653,25 +655,25 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); @@ -684,19 +686,19 @@ mod tests { let mut jdb = new_db(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -705,24 +707,24 @@ mod tests { fn fork_same_key_one() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -730,24 +732,24 @@ mod tests { #[test] fn fork_same_key_other() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -755,33 +757,33 @@ mod tests { #[test] fn fork_ins_del_ins() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -800,7 +802,7 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar")); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); foo }; @@ -808,7 +810,7 @@ mod tests { { let mut jdb = EarlyMergeDB::new(shared_db.clone(), None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -816,7 +818,7 @@ mod tests { let mut jdb = EarlyMergeDB::new(shared_db, None); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -830,22 +832,22 @@ mod tests { // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // expunge foo - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -856,43 +858,43 @@ mod tests { // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1a"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2a"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2b"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3a"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3b"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // expunge foo - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -902,25 +904,25 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -931,30 +933,30 @@ mod tests { // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(3, &keccak(b"3"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -969,20 +971,20 @@ mod tests { let mut jdb = EarlyMergeDB::new(shared_db.clone(), None); // history is 1 jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -991,7 +993,7 @@ mod tests { let mut jdb = EarlyMergeDB::new(shared_db.clone(), None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -999,7 +1001,7 @@ mod tests { }; { let mut jdb = EarlyMergeDB::new(shared_db.clone(), None); - jdb.commit_batch(5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -1007,7 +1009,7 @@ mod tests { }; { let mut jdb = EarlyMergeDB::new(shared_db, None); - jdb.commit_batch(6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -1022,22 +1024,22 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); (foo, bar, baz) }; { let mut jdb = EarlyMergeDB::new(shared_db, None); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); @@ -1049,11 +1051,11 @@ mod tests { fn inject() { let mut jdb = new_db(); let key = jdb.insert(EMPTY_PREFIX, b"dog"); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog")); jdb.remove(&key, EMPTY_PREFIX); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert!(jdb.get(&key, EMPTY_PREFIX).is_none()); } diff --git a/util/journaldb/src/lib.rs b/util/journaldb/src/lib.rs index 0cd362ce241..0024b3638c0 100644 --- a/util/journaldb/src/lib.rs +++ b/util/journaldb/src/lib.rs @@ -16,51 +16,84 @@ //! `JournalDB` interface and implementation. -extern crate parity_util_mem; -extern crate parity_util_mem as mem; -extern crate parity_util_mem as malloc_size_of; -#[macro_use] -extern crate log; - -extern crate ethereum_types; -extern crate parity_bytes as bytes; -extern crate hash_db; -extern crate keccak_hasher; -extern crate kvdb; -extern crate memory_db; -extern crate parking_lot; -extern crate fastmap; -extern crate rlp; +use std::{ + fmt, str, io, + sync::Arc, + collections::HashMap, +}; + +use ethereum_types::H256; +use hash_db::HashDB; +use keccak_hasher::KeccakHasher; +use kvdb::{self, DBTransaction, DBValue}; +use parity_bytes::Bytes; -#[cfg(test)] -extern crate env_logger; -#[cfg(test)] -extern crate keccak_hash as keccak; -#[cfg(test)] -extern crate kvdb_memorydb; - -use std::{fmt, str, io}; -use std::sync::Arc; - -/// Export the journaldb module. -mod traits; mod archivedb; mod earlymergedb; mod overlayrecentdb; mod refcounteddb; mod util; mod as_hash_db_impls; +mod overlaydb; + +/// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually +/// exclusive actions. +pub trait JournalDB: HashDB { + /// Return a copy of ourself, in a box. + fn boxed_clone(&self) -> Box; + + /// Returns heap memory size used + fn mem_used(&self) -> usize; -pub mod overlaydb; + /// Returns the size of journalled state in memory. + /// This function has a considerable speed requirement -- + /// it must be fast enough to call several times per block imported. + fn journal_size(&self) -> usize { 0 } + + /// Check if this database has any commits + fn is_empty(&self) -> bool; + + /// Get the earliest era in the DB. None if there isn't yet any data in there. + fn earliest_era(&self) -> Option { None } + + /// Get the latest era in the DB. None if there isn't yet any data in there. + fn latest_era(&self) -> Option; + + /// Journal recent database operations as being associated with a given era and id. + // TODO: give the overlay to this function so journaldbs don't manage the overlays themselves. + fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result; + + /// Mark a given block as canonical, indicating that competing blocks' states may be pruned out. + fn mark_canonical(&mut self, batch: &mut DBTransaction, era: u64, id: &H256) -> io::Result; + + /// Commit all queued insert and delete operations without affecting any journalling -- this requires that all insertions + /// and deletions are indeed canonical and will likely lead to an invalid database if that assumption is violated. + /// + /// Any keys or values inserted or deleted must be completely independent of those affected + /// by any previous `commit` operations. Essentially, this means that `inject` can be used + /// either to restore a state to a fresh database, or to insert data which may only be journalled + /// from this point onwards. + fn inject(&mut self, batch: &mut DBTransaction) -> io::Result; -/// Export the `JournalDB` trait. -pub use self::traits::JournalDB; + /// State data query + fn state(&self, _id: &H256) -> Option; -/// Export keyed hash trait -pub use self::traits::KeyedHashDB; -/// Export as keyed hash trait -pub use self::traits::AsKeyedHashDB; + /// Whether this database is pruned. + fn is_prunable(&self) -> bool { true } + /// Get backing database. + fn backing(&self) -> &Arc; + + /// Clear internal strucutres. This should called after changes have been written + /// to the backing strage + fn flush(&self) {} + + /// Consolidate all the insertions and deletions in the given memory overlay. + fn consolidate(&mut self, overlay: MemoryDB); + + /// Primarily use for tests, highly inefficient. + fn keys(&self) -> HashMap; +} /// Alias to ethereum MemoryDB type MemoryDB = memory_db::MemoryDB< @@ -177,6 +210,29 @@ pub fn new_memory_db() -> MemoryDB { MemoryDB::from_null_node(&rlp::NULL_RLP, rlp::NULL_RLP.as_ref().into()) } +#[cfg(test)] +/// Inject all changes in a single batch. +pub fn inject_batch(jdb: &mut dyn JournalDB) -> io::Result { + let mut batch = jdb.backing().transaction(); + let res = jdb.inject(&mut batch)?; + jdb.backing().write(batch).map(|_| res).map_err(Into::into) +} + +/// Commit all changes in a single batch +#[cfg(test)] +fn commit_batch(jdb: &mut dyn JournalDB, now: u64, id: &H256, end: Option<(u64, H256)>) -> io::Result { + let mut batch = jdb.backing().transaction(); + let mut ops = jdb.journal_under(&mut batch, now, id)?; + + if let Some((end_era, canon_id)) = end { + ops += jdb.mark_canonical(&mut batch, end_era, &canon_id)?; + } + + let result = jdb.backing().write(batch).map(|_| ops).map_err(Into::into); + jdb.flush(); + result +} + #[cfg(test)] mod tests { use super::Algorithm; diff --git a/util/journaldb/src/overlaydb.rs b/util/journaldb/src/overlaydb.rs index 06b0ebed927..44870acf161 100644 --- a/util/journaldb/src/overlaydb.rs +++ b/util/journaldb/src/overlaydb.rs @@ -16,17 +16,20 @@ //! Disk-backed `HashDB` implementation. -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::io; -use std::sync::Arc; +use std::{ + collections::{HashMap, hash_map::Entry}, + io, + sync::Arc, +}; use ethereum_types::H256; -use rlp::{Rlp, RlpStream, Encodable, DecoderError, Decodable, encode, decode}; -use hash_db::{HashDB, Prefix, EMPTY_PREFIX}; +use hash_db::{HashDB, Prefix}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; -use super::{error_negatively_reference_hash}; +use log::trace; +use rlp::{Rlp, RlpStream, Encodable, DecoderError, Decodable, encode, decode}; + +use crate::{error_negatively_reference_hash, new_memory_db}; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay. /// @@ -78,8 +81,12 @@ impl Decodable for Payload { impl OverlayDB { /// Create a new instance of OverlayDB given a `backing` database. - pub fn new(backing: Arc, col: Option) -> OverlayDB { - OverlayDB{ overlay: ::new_memory_db(), backing: backing, column: col } + pub fn new(backing: Arc, column: Option) -> OverlayDB { + OverlayDB { + overlay: new_memory_db(), + backing, + column, + } } /// Create a new instance of OverlayDB with an anonymous temporary database. @@ -128,13 +135,6 @@ impl OverlayDB { Ok(ret) } - /// Revert all operations on this object (i.e. `insert()`s and `remove()`s) since the - /// last `commit()`. - pub fn revert(&mut self) { self.overlay.clear(); } - - /// Get the number of references that would be committed. - pub fn commit_refs(&self, key: &H256) -> i32 { self.overlay.raw(key, EMPTY_PREFIX).map_or(0, |(_, refs)| refs) } - /// Get the refs and value of the given key. fn payload(&self, key: &H256) -> Option { self.backing.get(self.column, key.as_bytes()) @@ -153,10 +153,7 @@ impl OverlayDB { } } -} - -impl crate::KeyedHashDB for OverlayDB { - fn keys(&self) -> HashMap { + pub fn keys(&self) -> HashMap { let mut ret: HashMap = self.backing.iter(self.column) .map(|(key, _)| { let h = H256::from_slice(&*key); @@ -177,7 +174,6 @@ impl crate::KeyedHashDB for OverlayDB { } ret } - } impl HashDB for OverlayDB { @@ -233,106 +229,103 @@ impl HashDB for OverlayDB { fn remove(&mut self, key: &H256, prefix: Prefix) { self.overlay.remove(key, prefix); } } -#[test] -fn overlaydb_revert() { - let mut m = OverlayDB::new_temp(); - let foo = m.insert(EMPTY_PREFIX, b"foo"); // insert foo. - let mut batch = m.backing.transaction(); - m.commit_to_batch(&mut batch).unwrap(); // commit - new operations begin here... - m.backing.write(batch).unwrap(); - let bar = m.insert(EMPTY_PREFIX, b"bar"); // insert bar. - m.remove(&foo, EMPTY_PREFIX); // remove foo. - assert!(!m.contains(&foo, EMPTY_PREFIX)); // foo is gone. - assert!(m.contains(&bar, EMPTY_PREFIX)); // bar is here. - m.revert(); // revert the last two operations. - assert!(m.contains(&foo, EMPTY_PREFIX)); // foo is here. - assert!(!m.contains(&bar, EMPTY_PREFIX)); // bar is gone. -} +#[cfg(test)] +mod tests { + use hash_db::EMPTY_PREFIX; + use super::*; + + #[test] + fn overlaydb_revert() { + let mut m = OverlayDB::new_temp(); + let foo = m.insert(EMPTY_PREFIX, b"foo"); // insert foo. + let mut batch = m.backing.transaction(); + m.commit_to_batch(&mut batch).unwrap(); // commit - new operations begin here... + m.backing.write(batch).unwrap(); + let bar = m.insert(EMPTY_PREFIX, b"bar"); // insert bar. + m.remove(&foo, EMPTY_PREFIX); // remove foo. + assert!(!m.contains(&foo, EMPTY_PREFIX)); // foo is gone. + assert!(m.contains(&bar, EMPTY_PREFIX)); // bar is here. + } -#[test] -fn overlaydb_overlay_insert_and_remove() { - let mut trie = OverlayDB::new_temp(); - let h = trie.insert(EMPTY_PREFIX, b"hello world"); - assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); - trie.remove(&h, EMPTY_PREFIX); - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); -} + #[test] + fn overlaydb_overlay_insert_and_remove() { + let mut trie = OverlayDB::new_temp(); + let h = trie.insert(EMPTY_PREFIX, b"hello world"); + assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); + trie.remove(&h, EMPTY_PREFIX); + assert_eq!(trie.get(&h, EMPTY_PREFIX), None); + } -#[test] -fn overlaydb_backing_insert_revert() { - let mut trie = OverlayDB::new_temp(); - let h = trie.insert(EMPTY_PREFIX, b"hello world"); - assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); - trie.commit().unwrap(); - assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); - trie.revert(); - assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); -} + #[test] + fn overlaydb_backing_insert_revert() { + let mut trie = OverlayDB::new_temp(); + let h = trie.insert(EMPTY_PREFIX, b"hello world"); + assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); + trie.commit().unwrap(); + assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); + } -#[test] -fn overlaydb_backing_remove() { - let mut trie = OverlayDB::new_temp(); - let h = trie.insert(EMPTY_PREFIX, b"hello world"); - trie.commit().unwrap(); - trie.remove(&h, EMPTY_PREFIX); - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); - trie.commit().unwrap(); - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); - trie.revert(); - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); -} + #[test] + fn overlaydb_backing_remove() { + let mut trie = OverlayDB::new_temp(); + let h = trie.insert(EMPTY_PREFIX, b"hello world"); + trie.commit().unwrap(); + trie.remove(&h, EMPTY_PREFIX); + assert_eq!(trie.get(&h, EMPTY_PREFIX), None); + trie.commit().unwrap(); + assert_eq!(trie.get(&h, EMPTY_PREFIX), None); + } -#[test] -fn overlaydb_backing_remove_revert() { - let mut trie = OverlayDB::new_temp(); - let h = trie.insert(EMPTY_PREFIX, b"hello world"); - trie.commit().unwrap(); - trie.remove(&h, EMPTY_PREFIX); - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); - trie.revert(); - assert_eq!(trie.get(&h, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"hello world")); -} + #[test] + fn overlaydb_backing_remove_revert() { + let mut trie = OverlayDB::new_temp(); + let h = trie.insert(EMPTY_PREFIX, b"hello world"); + trie.commit().unwrap(); + trie.remove(&h, EMPTY_PREFIX); + assert_eq!(trie.get(&h, EMPTY_PREFIX), None); + } -#[test] -fn overlaydb_negative() { - let mut trie = OverlayDB::new_temp(); - let h = trie.insert(EMPTY_PREFIX, b"hello world"); - trie.commit().unwrap(); - trie.remove(&h, EMPTY_PREFIX); - trie.remove(&h, EMPTY_PREFIX); //bad - sends us into negative refs. - assert_eq!(trie.get(&h, EMPTY_PREFIX), None); - assert!(trie.commit().is_err()); -} + #[test] + fn overlaydb_negative() { + let mut trie = OverlayDB::new_temp(); + let h = trie.insert(EMPTY_PREFIX, b"hello world"); + trie.commit().unwrap(); + trie.remove(&h, EMPTY_PREFIX); + trie.remove(&h, EMPTY_PREFIX); //bad - sends us into negative refs. + assert_eq!(trie.get(&h, EMPTY_PREFIX), None); + assert!(trie.commit().is_err()); + } -#[test] -fn overlaydb_complex() { - let mut trie = OverlayDB::new_temp(); - let hfoo = trie.insert(EMPTY_PREFIX, b"foo"); - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - let hbar = trie.insert(EMPTY_PREFIX, b"bar"); - assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); - trie.commit().unwrap(); - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); - trie.insert(EMPTY_PREFIX, b"foo"); // two refs - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - trie.commit().unwrap(); - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); - trie.remove(&hbar, EMPTY_PREFIX); // zero refs - delete - assert_eq!(trie.get(&hbar, EMPTY_PREFIX), None); - trie.remove(&hfoo, EMPTY_PREFIX); // one ref - keep - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - trie.commit().unwrap(); - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - would delete, but... - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); - trie.insert(EMPTY_PREFIX, b"foo"); // one ref - keep after all. - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - trie.commit().unwrap(); - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); - trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - delete - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); - trie.commit().unwrap(); // - assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); + #[test] + fn overlaydb_complex() { + let mut trie = OverlayDB::new_temp(); + let hfoo = trie.insert(EMPTY_PREFIX, b"foo"); + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + let hbar = trie.insert(EMPTY_PREFIX, b"bar"); + assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); + trie.commit().unwrap(); + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); + trie.insert(EMPTY_PREFIX, b"foo"); // two refs + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + trie.commit().unwrap(); + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + assert_eq!(trie.get(&hbar, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"bar")); + trie.remove(&hbar, EMPTY_PREFIX); // zero refs - delete + assert_eq!(trie.get(&hbar, EMPTY_PREFIX), None); + trie.remove(&hfoo, EMPTY_PREFIX); // one ref - keep + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + trie.commit().unwrap(); + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - would delete, but... + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); + trie.insert(EMPTY_PREFIX, b"foo"); // one ref - keep after all. + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + trie.commit().unwrap(); + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"foo")); + trie.remove(&hfoo, EMPTY_PREFIX); // zero ref - delete + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); + trie.commit().unwrap(); // + assert_eq!(trie.get(&hfoo, EMPTY_PREFIX), None); + } } diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index 3a1e7d293f4..0c0f92d5eb0 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -16,22 +16,28 @@ //! `JournalDB` over in-memory overlay -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::io; -use std::sync::Arc; +use std::{ + collections::{HashMap, hash_map::Entry}, + io, + sync::Arc, +}; -use bytes::Bytes; use ethereum_types::H256; +use fastmap::H256FastMap; use hash_db::{HashDB, Prefix, EMPTY_PREFIX}; -use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; +use log::trace; +use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops}; +use parity_bytes::Bytes; use parking_lot::RwLock; -use fastmap::H256FastMap; use rlp::{Rlp, RlpStream, encode, decode, DecoderError, Decodable, Encodable}; -use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, JournalDB, error_negatively_reference_hash}; -use util::DatabaseKey; + +use crate::{ + DB_PREFIX_LEN, LATEST_ERA_KEY, JournalDB, error_negatively_reference_hash, + new_memory_db, + util::DatabaseKey +}; /// Implementation of the `JournalDB` trait for a disk-backed database with a memory overlay /// and, possibly, latent-removal semantics. @@ -150,7 +156,7 @@ impl OverlayRecentDB { pub fn new(backing: Arc, col: Option) -> OverlayRecentDB { let journal_overlay = Arc::new(RwLock::new(OverlayRecentDB::read_overlay(&*backing, col))); OverlayRecentDB { - transaction_overlay: ::new_memory_db(), + transaction_overlay: new_memory_db(), backing: backing, journal_overlay: journal_overlay, column: col, @@ -176,7 +182,7 @@ impl OverlayRecentDB { fn read_overlay(db: &dyn KeyValueDB, col: Option) -> JournalOverlay { let mut journal = HashMap::new(); - let mut overlay = ::new_memory_db(); + let mut overlay = new_memory_db(); let mut count = 0; let mut latest_era = None; let mut earliest_era = None; @@ -238,26 +244,6 @@ fn to_short_key(key: &H256) -> H256 { k } -impl ::traits::KeyedHashDB for OverlayRecentDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.transaction_overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } -} - impl JournalDB for OverlayRecentDB { fn boxed_clone(&self) -> Box { @@ -455,6 +441,24 @@ impl JournalDB for OverlayRecentDB { fn consolidate(&mut self, with: super::MemoryDB) { self.transaction_overlay.consolidate(with); } + + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.transaction_overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } } impl HashDB for OverlayRecentDB { @@ -490,11 +494,11 @@ impl HashDB for OverlayRecentDB { #[cfg(test)] mod tests { - - use keccak::keccak; + use keccak_hash::keccak; use super::*; use hash_db::{HashDB, EMPTY_PREFIX}; - use {kvdb_memorydb, JournalDB}; + use kvdb_memorydb; + use crate::{JournalDB, inject_batch, commit_batch}; fn new_db() -> OverlayRecentDB { let backing = Arc::new(kvdb_memorydb::create(0)); @@ -507,25 +511,25 @@ mod tests { let mut jdb = new_db(); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002a"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003a"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&x, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"1002b"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); let x = jdb.insert(EMPTY_PREFIX, b"X"); - jdb.commit_batch(4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"1003b"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"1004a"), Some((3, keccak(b"1002a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"1005a"), Some((4, keccak(b"1003a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&x, EMPTY_PREFIX)); @@ -536,20 +540,20 @@ mod tests { // history is 3 let mut jdb = new_db(); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); jdb.remove(&h, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&h, EMPTY_PREFIX)); } @@ -561,7 +565,7 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -569,7 +573,7 @@ mod tests { jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -577,20 +581,20 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.remove(&baz, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); @@ -604,25 +608,25 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); @@ -635,19 +639,19 @@ mod tests { let mut jdb = new_db(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"2"), Some((0, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -655,24 +659,24 @@ mod tests { #[test] fn fork_same_key_one() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((1, keccak(b"1a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -681,24 +685,24 @@ mod tests { fn fork_same_key_other() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1c"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); } @@ -707,33 +711,33 @@ mod tests { fn fork_ins_del_ins() { let mut jdb = new_db(); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3a"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3b"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((2, keccak(b"2a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5a"), Some((3, keccak(b"3a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -747,7 +751,7 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.emplace(bar.clone(), EMPTY_PREFIX, DBValue::from_slice(b"bar")); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); foo }; @@ -755,7 +759,7 @@ mod tests { { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -763,7 +767,7 @@ mod tests { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -776,22 +780,22 @@ mod tests { // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // expunge foo - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -802,43 +806,43 @@ mod tests { // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1a"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2a"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(2, &keccak(b"2b"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3a"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3b"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // expunge foo - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -847,25 +851,25 @@ mod tests { let mut jdb = new_db(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); // BROKEN assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((4, keccak(b"4")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -875,30 +879,30 @@ mod tests { let mut jdb = new_db(); // history is 4 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(3, &keccak(b"3"), None).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"6"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(EMPTY_PREFIX, b"foo"); jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 7, &keccak(b"7"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); } @@ -913,20 +917,20 @@ mod tests { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); // history is 1 jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); // foo is ancient history. jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -935,7 +939,7 @@ mod tests { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -943,7 +947,7 @@ mod tests { }; { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); - jdb.commit_batch(5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 5, &keccak(b"5"), Some((3, keccak(b"3")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); @@ -951,7 +955,7 @@ mod tests { }; { let mut jdb = OverlayRecentDB::new(shared_db, None); - jdb.commit_batch(6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap(); + commit_batch(&mut jdb, 6, &keccak(b"6"), Some((4, keccak(b"4")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); } @@ -966,22 +970,22 @@ mod tests { // history is 1 let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.can_reconstruct_refs()); (foo, bar, baz) }; { let mut jdb = OverlayRecentDB::new(shared_db, None); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); @@ -993,17 +997,17 @@ mod tests { fn insert_older_era() { let mut jdb = new_db(); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0a"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0a"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0a")))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(0, &keccak(b"0b"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0b"), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); @@ -1013,11 +1017,11 @@ mod tests { fn inject() { let mut jdb = new_db(); let key = jdb.insert(EMPTY_PREFIX, b"dog"); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog")); jdb.remove(&key, EMPTY_PREFIX); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert!(jdb.get(&key, EMPTY_PREFIX).is_none()); } diff --git a/util/journaldb/src/refcounteddb.rs b/util/journaldb/src/refcounteddb.rs index 4aef98c302c..884ed1bace6 100644 --- a/util/journaldb/src/refcounteddb.rs +++ b/util/journaldb/src/refcounteddb.rs @@ -16,21 +16,26 @@ //! Disk-backed, ref-counted `JournalDB` implementation. -use std::collections::HashMap; -use std::io; -use std::sync::Arc; +use std::{ + io, + sync::Arc, + collections::HashMap, +}; -use bytes::Bytes; use ethereum_types::H256; use hash_db::{HashDB, Prefix, EMPTY_PREFIX}; -use parity_util_mem::{MallocSizeOf, allocators::new_malloc_size_ops}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; -use overlaydb::OverlayDB; +use log::trace; +use malloc_size_of::{MallocSizeOf, allocators::new_malloc_size_ops}; +use parity_bytes::Bytes; use rlp::{encode, decode}; -use super::{DB_PREFIX_LEN, LATEST_ERA_KEY}; -use super::traits::JournalDB; -use util::{DatabaseKey, DatabaseValueView, DatabaseValueRef}; + +use crate::{ + overlaydb::OverlayDB, + JournalDB, DB_PREFIX_LEN, LATEST_ERA_KEY, + util::{DatabaseKey, DatabaseValueView, DatabaseValueRef}, +}; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay /// and latent-removal semantics. @@ -87,10 +92,6 @@ impl HashDB for RefCountedDB { fn remove(&mut self, key: &H256, _prefix: Prefix) { self.removes.push(key.clone()); } } -impl ::traits::KeyedHashDB for RefCountedDB { - fn keys(&self) -> HashMap { self.forward.keys() } -} - impl JournalDB for RefCountedDB { fn boxed_clone(&self) -> Box { Box::new(RefCountedDB { @@ -213,15 +214,19 @@ impl JournalDB for RefCountedDB { } } } + + fn keys(&self) -> HashMap { + self.forward.keys() + } } #[cfg(test)] mod tests { - - use keccak::keccak; + use keccak_hash::keccak; use hash_db::{HashDB, EMPTY_PREFIX}; use super::*; - use {JournalDB, kvdb_memorydb}; + use kvdb_memorydb; + use crate::{JournalDB, inject_batch, commit_batch}; fn new_db() -> RefCountedDB { let backing = Arc::new(kvdb_memorydb::create(0)); @@ -233,16 +238,16 @@ mod tests { // history is 3 let mut jdb = new_db(); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); jdb.remove(&h, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&h, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); assert!(!jdb.contains(&h, EMPTY_PREFIX)); } @@ -252,16 +257,16 @@ mod tests { let mut jdb = new_db(); assert_eq!(jdb.latest_era(), None); let h = jdb.insert(EMPTY_PREFIX, b"foo"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert_eq!(jdb.latest_era(), Some(0)); jdb.remove(&h, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), None).unwrap(); assert_eq!(jdb.latest_era(), Some(1)); - jdb.commit_batch(2, &keccak(b"2"), None).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), None).unwrap(); assert_eq!(jdb.latest_era(), Some(2)); - jdb.commit_batch(3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((0, keccak(b"0")))).unwrap(); assert_eq!(jdb.latest_era(), Some(3)); - jdb.commit_batch(4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((1, keccak(b"1")))).unwrap(); assert_eq!(jdb.latest_era(), Some(4)); } @@ -272,32 +277,32 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); jdb.remove(&bar, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); let foo = jdb.insert(EMPTY_PREFIX, b"foo"); jdb.remove(&baz, EMPTY_PREFIX); - jdb.commit_batch(2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2"), Some((1, keccak(b"1")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); - jdb.commit_batch(3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); + commit_batch(&mut jdb, 3, &keccak(b"3"), Some((2, keccak(b"2")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); + commit_batch(&mut jdb, 4, &keccak(b"4"), Some((3, keccak(b"3")))).unwrap(); assert!(!jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); @@ -310,22 +315,22 @@ mod tests { let foo = jdb.insert(EMPTY_PREFIX, b"foo"); let bar = jdb.insert(EMPTY_PREFIX, b"bar"); - jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); + commit_batch(&mut jdb, 0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); jdb.remove(&foo, EMPTY_PREFIX); let baz = jdb.insert(EMPTY_PREFIX, b"baz"); - jdb.commit_batch(1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1a"), Some((0, keccak(b"0")))).unwrap(); jdb.remove(&bar, EMPTY_PREFIX); - jdb.commit_batch(1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); + commit_batch(&mut jdb, 1, &keccak(b"1b"), Some((0, keccak(b"0")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(jdb.contains(&bar, EMPTY_PREFIX)); assert!(jdb.contains(&baz, EMPTY_PREFIX)); - jdb.commit_batch(2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); + commit_batch(&mut jdb, 2, &keccak(b"2b"), Some((1, keccak(b"1b")))).unwrap(); assert!(jdb.contains(&foo, EMPTY_PREFIX)); assert!(!jdb.contains(&baz, EMPTY_PREFIX)); assert!(!jdb.contains(&bar, EMPTY_PREFIX)); @@ -335,11 +340,11 @@ mod tests { fn inject() { let mut jdb = new_db(); let key = jdb.insert(EMPTY_PREFIX, b"dog"); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert_eq!(jdb.get(&key, EMPTY_PREFIX).unwrap(), DBValue::from_slice(b"dog")); jdb.remove(&key, EMPTY_PREFIX); - jdb.inject_batch().unwrap(); + inject_batch(&mut jdb).unwrap(); assert!(jdb.get(&key, EMPTY_PREFIX).is_none()); } diff --git a/util/journaldb/src/traits.rs b/util/journaldb/src/traits.rs deleted file mode 100644 index 5114074a544..00000000000 --- a/util/journaldb/src/traits.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Disk-backed `HashDB` implementation. - -use std::io; -use std::sync::Arc; - -use bytes::Bytes; -use ethereum_types::H256; -use hash_db::{HashDB, AsHashDB}; -use keccak_hasher::KeccakHasher; -use kvdb::{self, DBTransaction, DBValue}; -use std::collections::HashMap; - - -/// expose keys of a hashDB for debugging or tests (slow). -pub trait KeyedHashDB: HashDB { - /// Primarily use for tests, highly inefficient. - fn keys(&self) -> HashMap; -} - -/// Upcast to `KeyedHashDB` -pub trait AsKeyedHashDB: AsHashDB { - /// Perform upcast to KeyedHashDB. - fn as_keyed_hash_db(&self) -> &dyn KeyedHashDB; -} - -/// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually -/// exclusive actions. -pub trait JournalDB: KeyedHashDB { - - /// Return a copy of ourself, in a box. - fn boxed_clone(&self) -> Box; - - /// Returns heap memory size used - fn mem_used(&self) -> usize; - - /// Returns the size of journalled state in memory. - /// This function has a considerable speed requirement -- - /// it must be fast enough to call several times per block imported. - fn journal_size(&self) -> usize { 0 } - - /// Check if this database has any commits - fn is_empty(&self) -> bool; - - /// Get the earliest era in the DB. None if there isn't yet any data in there. - fn earliest_era(&self) -> Option { None } - - /// Get the latest era in the DB. None if there isn't yet any data in there. - fn latest_era(&self) -> Option; - - /// Journal recent database operations as being associated with a given era and id. - // TODO: give the overlay to this function so journaldbs don't manage the overlays themselves. - fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result; - - /// Mark a given block as canonical, indicating that competing blocks' states may be pruned out. - fn mark_canonical(&mut self, batch: &mut DBTransaction, era: u64, id: &H256) -> io::Result; - - /// Commit all queued insert and delete operations without affecting any journalling -- this requires that all insertions - /// and deletions are indeed canonical and will likely lead to an invalid database if that assumption is violated. - /// - /// Any keys or values inserted or deleted must be completely independent of those affected - /// by any previous `commit` operations. Essentially, this means that `inject` can be used - /// either to restore a state to a fresh database, or to insert data which may only be journalled - /// from this point onwards. - fn inject(&mut self, batch: &mut DBTransaction) -> io::Result; - - /// State data query - fn state(&self, _id: &H256) -> Option; - - /// Whether this database is pruned. - fn is_prunable(&self) -> bool { true } - - /// Get backing database. - fn backing(&self) -> &Arc; - - /// Clear internal strucutres. This should called after changes have been written - /// to the backing strage - fn flush(&self) {} - - /// Consolidate all the insertions and deletions in the given memory overlay. - fn consolidate(&mut self, overlay: super::MemoryDB); - - /// Commit all changes in a single batch - #[cfg(test)] - fn commit_batch(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> io::Result { - let mut batch = self.backing().transaction(); - let mut ops = self.journal_under(&mut batch, now, id)?; - - if let Some((end_era, canon_id)) = end { - ops += self.mark_canonical(&mut batch, end_era, &canon_id)?; - } - - let result = self.backing().write(batch).map(|_| ops).map_err(Into::into); - self.flush(); - result - } - - /// Inject all changes in a single batch. - #[cfg(test)] - fn inject_batch(&mut self) -> io::Result { - let mut batch = self.backing().transaction(); - let res = self.inject(&mut batch)?; - self.backing().write(batch).map(|_| res).map_err(Into::into) - } -}