JournalDB passing all tests.
This commit is contained in:
parent
193d615f9a
commit
28c07cba52
@ -26,8 +26,6 @@ impl JournalDB {
|
|||||||
/// Create a new instance given a `backing` database.
|
/// Create a new instance given a `backing` database.
|
||||||
pub fn new(backing: DB) -> JournalDB {
|
pub fn new(backing: DB) -> JournalDB {
|
||||||
let db = Arc::new(backing);
|
let db = Arc::new(backing);
|
||||||
// TODO: check it doesn't overwrite anything before.
|
|
||||||
// TODO: proper handling of errors (return )
|
|
||||||
JournalDB {
|
JournalDB {
|
||||||
forward: OverlayDB::new_with_arc(db.clone()),
|
forward: OverlayDB::new_with_arc(db.clone()),
|
||||||
backing: db,
|
backing: db,
|
||||||
@ -48,7 +46,7 @@ impl JournalDB {
|
|||||||
|
|
||||||
/// Commit all recent insert operations and historical removals from the old era
|
/// Commit all recent insert operations and historical removals from the old era
|
||||||
/// to the backing database.
|
/// to the backing database.
|
||||||
pub fn commit(&mut self, now: u64, id: &H256, end_era: u64, canon_id: &H256) -> Result<u32, UtilError> {
|
pub fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, &H256)>) -> Result<u32, UtilError> {
|
||||||
// journal format:
|
// journal format:
|
||||||
// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
|
// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
|
||||||
// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
|
// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
|
||||||
@ -81,30 +79,31 @@ impl JournalDB {
|
|||||||
r.append(&self.inserts);
|
r.append(&self.inserts);
|
||||||
r.append(&self.removes);
|
r.append(&self.removes);
|
||||||
try!(self.backing.put(&last, &r.out()));
|
try!(self.backing.put(&last, &r.out()));
|
||||||
|
self.inserts.clear();
|
||||||
|
self.removes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply old commits' details
|
// apply old commits' details
|
||||||
let mut index = 0usize;
|
if let Some((end_era, canon_id)) = end {
|
||||||
let mut last;
|
let mut index = 0usize;
|
||||||
while let Some(rlp_data) = try!(self.backing.get({
|
let mut last;
|
||||||
let mut r = RlpStream::new_list(2);
|
while let Some(rlp_data) = try!(self.backing.get({
|
||||||
r.append(&end_era);
|
let mut r = RlpStream::new_list(2);
|
||||||
r.append(&index);
|
r.append(&end_era);
|
||||||
last = r.out();
|
r.append(&index);
|
||||||
&last
|
last = r.out();
|
||||||
})) {
|
&last
|
||||||
let rlp = Rlp::new(&rlp_data);
|
})) {
|
||||||
let to_remove: Vec<H256> = rlp.val_at(if *canon_id == rlp.val_at(0) {2} else {1});
|
let rlp = Rlp::new(&rlp_data);
|
||||||
for i in to_remove.iter() {
|
let to_remove: Vec<H256> = rlp.val_at(if *canon_id == rlp.val_at(0) {2} else {1});
|
||||||
self.forward.remove(i);
|
for i in to_remove.iter() {
|
||||||
|
self.forward.remove(i);
|
||||||
|
}
|
||||||
|
try!(self.backing.delete(&last));
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
try!(self.backing.delete(&last));
|
|
||||||
index += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inserts.clear();
|
|
||||||
self.removes.clear();
|
|
||||||
|
|
||||||
self.forward.commit()
|
self.forward.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,3 +120,94 @@ impl HashDB for JournalDB {
|
|||||||
fn emplace(&mut self, key: H256, value: Bytes) { self.inserts.push(key.clone()); self.forward.emplace(key, value); }
|
fn emplace(&mut self, key: H256, value: Bytes) { self.inserts.push(key.clone()); self.forward.emplace(key, value); }
|
||||||
fn kill(&mut self, key: &H256) { self.removes.push(key.clone()); }
|
fn kill(&mut self, key: &H256) { self.removes.push(key.clone()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use common::*;
|
||||||
|
use super::*;
|
||||||
|
use hashdb::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn long_history() {
|
||||||
|
// history is 3
|
||||||
|
let mut jdb = JournalDB::new_temp();
|
||||||
|
let h = jdb.insert(b"foo");
|
||||||
|
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||||
|
assert!(jdb.exists(&h));
|
||||||
|
jdb.remove(&h);
|
||||||
|
jdb.commit(1, &b"1".sha3(), None).unwrap();
|
||||||
|
assert!(jdb.exists(&h));
|
||||||
|
jdb.commit(2, &b"2".sha3(), None).unwrap();
|
||||||
|
assert!(jdb.exists(&h));
|
||||||
|
jdb.commit(3, &b"3".sha3(), Some((0, &b"0".sha3()))).unwrap();
|
||||||
|
assert!(jdb.exists(&h));
|
||||||
|
jdb.commit(4, &b"4".sha3(), Some((1, &b"1".sha3()))).unwrap();
|
||||||
|
assert!(!jdb.exists(&h));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn complex() {
|
||||||
|
// history is 1
|
||||||
|
let mut jdb = JournalDB::new_temp();
|
||||||
|
|
||||||
|
let foo = jdb.insert(b"foo");
|
||||||
|
let bar = jdb.insert(b"bar");
|
||||||
|
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(jdb.exists(&bar));
|
||||||
|
|
||||||
|
jdb.remove(&foo);
|
||||||
|
jdb.remove(&bar);
|
||||||
|
let baz = jdb.insert(b"baz");
|
||||||
|
jdb.commit(1, &b"1".sha3(), Some((0, &b"0".sha3()))).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(jdb.exists(&bar));
|
||||||
|
assert!(jdb.exists(&baz));
|
||||||
|
|
||||||
|
let foo = jdb.insert(b"foo");
|
||||||
|
jdb.remove(&baz);
|
||||||
|
jdb.commit(2, &b"2".sha3(), Some((1, &b"1".sha3()))).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(!jdb.exists(&bar));
|
||||||
|
assert!(jdb.exists(&baz));
|
||||||
|
|
||||||
|
jdb.remove(&foo);
|
||||||
|
jdb.commit(3, &b"3".sha3(), Some((2, &b"2".sha3()))).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(!jdb.exists(&bar));
|
||||||
|
assert!(!jdb.exists(&baz));
|
||||||
|
|
||||||
|
jdb.commit(4, &b"4".sha3(), Some((3, &b"3".sha3()))).unwrap();
|
||||||
|
assert!(!jdb.exists(&foo));
|
||||||
|
assert!(!jdb.exists(&bar));
|
||||||
|
assert!(!jdb.exists(&baz));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fork() {
|
||||||
|
// history is 1
|
||||||
|
let mut jdb = JournalDB::new_temp();
|
||||||
|
|
||||||
|
let foo = jdb.insert(b"foo");
|
||||||
|
let bar = jdb.insert(b"bar");
|
||||||
|
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(jdb.exists(&bar));
|
||||||
|
|
||||||
|
jdb.remove(&foo);
|
||||||
|
let baz = jdb.insert(b"baz");
|
||||||
|
jdb.commit(1, &b"1a".sha3(), Some((0, &b"0".sha3()))).unwrap();
|
||||||
|
|
||||||
|
jdb.remove(&bar);
|
||||||
|
jdb.commit(1, &b"1b".sha3(), Some((0, &b"0".sha3()))).unwrap();
|
||||||
|
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(jdb.exists(&bar));
|
||||||
|
assert!(jdb.exists(&baz));
|
||||||
|
|
||||||
|
jdb.commit(2, &b"2b".sha3(), Some((1, &b"1b".sha3()))).unwrap();
|
||||||
|
assert!(jdb.exists(&foo));
|
||||||
|
assert!(!jdb.exists(&baz));
|
||||||
|
assert!(!jdb.exists(&bar));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user