Skip to content

Commit 8fcd391

Browse files
TrieDBMutBase added: no commit on drop (#226)
* explicit commit on drop * doc updated * trie-db: version bumped * review: docs * version bump * bool flag: commit_on_drop * tests added * fmt * fixes * versions bumped
1 parent f43bc12 commit 8fcd391

8 files changed

Lines changed: 130 additions & 16 deletions

File tree

test-support/reference-trie/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "reference-trie"
3-
version = "0.29.1"
3+
version = "0.29.2"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
description = "Simple reference trie format"
66
repository = "https://github.com/paritytech/trie/"
@@ -10,7 +10,7 @@ edition = "2018"
1010
[dependencies]
1111
hash-db = { path = "../../hash-db" , version = "0.16.0"}
1212
keccak-hasher = { path = "../keccak-hasher", version = "0.16.0" }
13-
trie-db = { path = "../../trie-db", default-features = false, version = "0.30.0" }
13+
trie-db = { path = "../../trie-db", default-features = false, version = "0.31.0" }
1414
trie-root = { path = "../../trie-root", default-features = false, version = "0.18.0" }
1515
parity-scale-codec = { version = "3.0.0", features = ["derive"] }
1616
hashbrown = { version = "0.14.1", default-features = false, features = ["ahash"] }

test-support/trie-bench/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "trie-bench"
33
description = "Standard benchmarking suite for tries"
4-
version = "0.42.0"
4+
version = "0.42.1"
55
authors = ["Parity Technologies <admin@parity.io>"]
66
repository = "https://github.com/paritytech/trie/"
77
license = "Apache-2.0"
@@ -13,6 +13,6 @@ trie-standardmap = { path = "../trie-standardmap", version = "0.16.0" }
1313
hash-db = { path = "../../hash-db" , version = "0.16.0"}
1414
memory-db = { path = "../../memory-db", version = "0.34.0" }
1515
trie-root = { path = "../../trie-root", version = "0.18.0" }
16-
trie-db = { path = "../../trie-db", version = "0.30.0" }
16+
trie-db = { path = "../../trie-db", version = "0.31.0" }
1717
criterion = "0.5.1"
1818
parity-scale-codec = "3.0.0"

trie-db/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "trie-db"
3-
version = "0.30.0"
3+
version = "0.31.0"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
description = "Merkle-Patricia Trie generic over key hasher and node encoding"
66
repository = "https://github.com/paritytech/trie"

trie-db/src/triedbmut.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ pub struct TrieDBMutBuilder<'db, L: TrieLayout> {
641641
root: &'db mut TrieHash<L>,
642642
cache: Option<&'db mut dyn TrieCache<L::Codec>>,
643643
recorder: Option<&'db mut dyn TrieRecorder<TrieHash<L>>>,
644+
commit_on_drop: bool,
644645
}
645646

646647
impl<'db, L: TrieLayout> TrieDBMutBuilder<'db, L> {
@@ -649,7 +650,7 @@ impl<'db, L: TrieLayout> TrieDBMutBuilder<'db, L> {
649650
pub fn new(db: &'db mut dyn HashDB<L::Hash, DBValue>, root: &'db mut TrieHash<L>) -> Self {
650651
*root = L::Codec::hashed_null_node();
651652

652-
Self { root, db, cache: None, recorder: None }
653+
Self { root, db, cache: None, recorder: None, commit_on_drop: true }
653654
}
654655

655656
/// Create a builder for constructing a new trie with the backing database `db` and `root`.
@@ -660,7 +661,7 @@ impl<'db, L: TrieLayout> TrieDBMutBuilder<'db, L> {
660661
db: &'db mut dyn HashDB<L::Hash, DBValue>,
661662
root: &'db mut TrieHash<L>,
662663
) -> Self {
663-
Self { db, root, cache: None, recorder: None }
664+
Self { db, root, cache: None, recorder: None, commit_on_drop: true }
664665
}
665666

666667
/// Use the given `cache` for the db.
@@ -695,7 +696,24 @@ impl<'db, L: TrieLayout> TrieDBMutBuilder<'db, L> {
695696
self
696697
}
697698

699+
/// Disable automatic commit on drop.
700+
///
701+
/// By default, [`TrieDBMut`] automatically commits changes when dropped. Calling this method
702+
/// disables that behavior, requiring explicit calls to [`TrieDBMut::commit`] to persist
703+
/// changes to the database.
704+
///
705+
/// This is useful when you want fine-grained control over when changes are committed, or when
706+
/// you want to avoid the performance cost of committing if you're just doing temporary
707+
/// operations.
708+
pub fn disable_commit_on_drop(mut self) -> Self {
709+
self.commit_on_drop = false;
710+
self
711+
}
712+
698713
/// Build the [`TrieDBMut`].
714+
///
715+
/// By default, the returned trie will automatically commit changes when dropped. Use
716+
/// [`disable_commit_on_drop`](Self::disable_commit_on_drop) to disable this behavior.
699717
pub fn build(self) -> TrieDBMut<'db, L> {
700718
let root_handle = NodeHandle::Hash(*self.root);
701719

@@ -707,17 +725,19 @@ impl<'db, L: TrieLayout> TrieDBMutBuilder<'db, L> {
707725
storage: NodeStorage::empty(),
708726
death_row: Default::default(),
709727
root_handle,
728+
commit_on_drop: self.commit_on_drop,
710729
}
711730
}
712731
}
713732

714733
/// A `Trie` implementation using a generic `HashDB` backing database.
715734
///
716-
/// Use it as a `TrieMut` trait object. You can use `db()` to get the backing database object.
735+
/// Use it as a [`TrieMut`] trait object. You can use `db()` to get the backing database object.
717736
/// Note that changes are not committed to the database until `commit` is called.
718737
///
719-
/// Querying the root or dropping the trie will commit automatically.
738+
/// Querying the root of the trie will commit automatically.
720739
///
740+
/// Dropping the instance may or may not commit depending on [Self::commit_on_drop] flag.
721741
///
722742
/// # Example
723743
/// ```ignore
@@ -751,6 +771,8 @@ where
751771
cache: Option<&'a mut dyn TrieCache<L::Codec>>,
752772
/// Optional trie recorder for recording trie accesses.
753773
recorder: Option<core::cell::RefCell<&'a mut dyn TrieRecorder<TrieHash<L>>>>,
774+
/// Whether to commit on drop.
775+
commit_on_drop: bool,
754776
}
755777

756778
impl<'a, L> TrieDBMut<'a, L>
@@ -2103,7 +2125,9 @@ where
21032125
L: TrieLayout,
21042126
{
21052127
fn drop(&mut self) {
2106-
self.commit();
2128+
if self.commit_on_drop {
2129+
self.commit();
2130+
}
21072131
}
21082132
}
21092133

trie-db/test/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "trie-db-test"
3-
version = "0.31.0"
3+
version = "0.31.1"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
description = "Tests for trie-db crate"
66
repository = "https://github.com/paritytech/trie"
@@ -12,7 +12,7 @@ name = "bench"
1212
harness = false
1313

1414
[dependencies]
15-
trie-db = { path = "..", version = "0.30.0"}
15+
trie-db = { path = "..", version = "0.31.0"}
1616
hash-db = { path = "../../hash-db", version = "0.16.0"}
1717
memory-db = { path = "../../memory-db", version = "0.34.0" }
1818
rand = { version = "0.8", default-features = false, features = ["small_rng"] }

trie-db/test/src/triedbmut.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,3 +890,93 @@ fn test_two_assets_memory_db_inner_2<T: TrieLayout>() {
890890
assert_eq!(state.get(key2.as_ref()).unwrap().unwrap(), data2);
891891
assert_eq!(state.get(key3.as_ref()).unwrap().unwrap(), data3);
892892
}
893+
894+
/// Prepare a non-empty trie for testing commit_on_drop behavior.
895+
/// Returns a database and root with one committed key-value pair.
896+
fn prepare_test_trie<T: TrieLayout>() -> (PrefixedMemoryDB<T>, <T::Hash as Hasher>::Out) {
897+
use hash_db::Hasher;
898+
899+
let mut memdb = PrefixedMemoryDB::<T>::default();
900+
let mut root = <T::Hash as Hasher>::Out::default();
901+
902+
let initial_data = vec![(b"existing_key".to_vec(), b"existing_value".to_vec())];
903+
populate_trie::<T>(&mut memdb, &mut root, &initial_data);
904+
905+
(memdb, root)
906+
}
907+
908+
test_layouts!(test_commit_on_drop_disabled, test_commit_on_drop_disabled_internal);
909+
fn test_commit_on_drop_disabled_internal<T: TrieLayout>() {
910+
let (mut memdb, mut root) = prepare_test_trie::<T>();
911+
let root_before = root.clone();
912+
let db_key_count_before = memdb.keys().len();
913+
914+
{
915+
let mut trie = TrieDBMutBuilder::<T>::from_existing(&mut memdb, &mut root)
916+
.disable_commit_on_drop()
917+
.build();
918+
trie.insert(b"test_key_1", b"test_value_1").unwrap();
919+
trie.insert(b"test_key_2", b"test_value_2").unwrap();
920+
trie.insert(b"test_key_3", b"test_value_3").unwrap();
921+
}
922+
923+
assert_eq!(root, root_before, "Root should not change after drop without commit");
924+
925+
let db_key_count_after = memdb.keys().len();
926+
assert_eq!(
927+
db_key_count_before, db_key_count_after,
928+
"Database should not gain new entries after drop without commit (before: {}, after: {})",
929+
db_key_count_before, db_key_count_after
930+
);
931+
}
932+
933+
test_layouts!(test_commit_on_drop_enabled, test_commit_on_drop_enabled_internal);
934+
fn test_commit_on_drop_enabled_internal<T: TrieLayout>() {
935+
let (mut memdb, mut root) = prepare_test_trie::<T>();
936+
let root_before = root.clone();
937+
let db_key_count_before = memdb.keys().len();
938+
939+
{
940+
let mut trie = TrieDBMutBuilder::<T>::from_existing(&mut memdb, &mut root).build();
941+
trie.insert(b"test_key_1", b"test_value_1").unwrap();
942+
trie.insert(b"test_key_2", b"test_value_2").unwrap();
943+
trie.insert(b"test_key_3", b"test_value_3").unwrap();
944+
}
945+
946+
assert_ne!(root, root_before, "Root should change after drop with auto-commit");
947+
948+
let db_key_count_after = memdb.keys().len();
949+
assert!(
950+
db_key_count_after > db_key_count_before,
951+
"Database should contain more nodes after drop with auto-commit (before: {}, after: {})",
952+
db_key_count_before,
953+
db_key_count_after
954+
);
955+
}
956+
957+
test_layouts!(test_commit_on_drop_explicit, test_commit_on_drop_explicit_internal);
958+
fn test_commit_on_drop_explicit_internal<T: TrieLayout>() {
959+
let (mut memdb, mut root) = prepare_test_trie::<T>();
960+
let root_before = root.clone();
961+
let db_key_count_before = memdb.keys().len();
962+
963+
{
964+
let mut trie = TrieDBMutBuilder::<T>::from_existing(&mut memdb, &mut root)
965+
.disable_commit_on_drop()
966+
.build();
967+
trie.insert(b"test_key_1", b"test_value_1").unwrap();
968+
trie.insert(b"test_key_2", b"test_value_2").unwrap();
969+
trie.insert(b"test_key_3", b"test_value_3").unwrap();
970+
trie.commit();
971+
}
972+
973+
assert_ne!(root, root_before, "Root should change after explicit commit");
974+
975+
let db_key_count_after = memdb.keys().len();
976+
assert!(
977+
db_key_count_after > db_key_count_before,
978+
"Database should contain more nodes after explicit commit (before: {}, after: {})",
979+
db_key_count_before,
980+
db_key_count_after
981+
);
982+
}

trie-eip1186/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[package]
22
name = "trie-eip1186"
3-
version = "0.5.0"
3+
version = "0.5.1"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
description = "EIP-1186 compliant proof generation and verification"
66
repository = "https://github.com/paritytech/trie"
77
license = "Apache-2.0"
88
edition = "2018"
99

1010
[dependencies]
11-
trie-db = { path = "../trie-db", default-features = false, version = "0.30.0"}
11+
trie-db = { path = "../trie-db", default-features = false, version = "0.31.0"}
1212
hash-db = { path = "../hash-db", default-features = false, version = "0.16.0"}
1313

1414
[features]

trie-eip1186/test/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "trie-eip1186-test"
3-
version = "0.7.0"
3+
version = "0.7.1"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
description = "Tests for trie-eip1186 crate"
66
repository = "https://github.com/paritytech/trie"
@@ -9,7 +9,7 @@ edition = "2018"
99

1010
[dependencies]
1111
trie-eip1186 = { path = "..", version = "0.5.0"}
12-
trie-db = { path = "../../trie-db", version = "0.30.0"}
12+
trie-db = { path = "../../trie-db", version = "0.31.0"}
1313
hash-db = { path = "../../hash-db", version = "0.16.0"}
1414
reference-trie = { path = "../../test-support/reference-trie", version = "0.29.0" }
1515
memory-db = { path = "../../memory-db", version = "0.34.0" }

0 commit comments

Comments
 (0)