Return number of keys removed when calling storage_kill on child trie (#8166)

* Initial piping of returning amount of keys killed

* One more test for `None` limit

* forgot to update

* fix return value

* use version 3

* Update to return `KillOutcome`

* Update name to KillChildStorageResult
This commit is contained in:
Shawn Tabrizi
2021-02-22 11:24:12 -08:00
committed by GitHub
parent 74a1d69477
commit d25229bc89
10 changed files with 100 additions and 40 deletions
@@ -211,9 +211,9 @@ impl Externalities for BasicExternalities {
&mut self,
child_info: &ChildInfo,
_limit: Option<u32>,
) -> bool {
self.inner.children_default.remove(child_info.storage_key());
true
) -> (bool, u32) {
let num_removed = self.inner.children_default.remove(child_info.storage_key()).map(|c| c.data.len()).unwrap_or(0);
(true, num_removed as u32)
}
fn clear_prefix(&mut self, prefix: &[u8]) {
@@ -411,6 +411,29 @@ mod tests {
assert_eq!(ext.child_storage(child_info, b"doe"), None);
}
#[test]
fn kill_child_storage_returns_num_elements_removed() {
let child_info = ChildInfo::new_default(b"storage_key");
let child_info = &child_info;
let mut ext = BasicExternalities::new(Storage {
top: Default::default(),
children_default: map![
child_info.storage_key().to_vec() => StorageChild {
data: map![
b"doe".to_vec() => b"reindeer".to_vec(),
b"dog".to_vec() => b"puppy".to_vec(),
b"hello".to_vec() => b"world".to_vec(),
],
child_info: child_info.to_owned(),
}
]
});
let res = ext.kill_child_storage(child_info, None);
assert_eq!(res, (true, 3));
}
#[test]
fn basic_externalities_is_empty() {
// Make sure no values are set by default in `BasicExternalities`.
@@ -391,7 +391,7 @@ where
&mut self,
child_info: &ChildInfo,
limit: Option<u32>,
) -> bool {
) -> (bool, u32) {
trace!(target: "state", "{:04x}: KillChild({})",
self.id,
HexDisplay::from(&child_info.storage_key()),
@@ -399,9 +399,9 @@ where
let _guard = guard();
self.mark_dirty();
self.overlay.clear_child_storage(child_info);
let mut num_deleted: u32 = 0;
if let Some(limit) = limit {
let mut num_deleted: u32 = 0;
let mut all_deleted = true;
self.backend.apply_to_child_keys_while(child_info, |key| {
if num_deleted == limit {
@@ -417,13 +417,14 @@ where
self.overlay.set_child_storage(child_info, key.to_vec(), None);
true
});
all_deleted
(all_deleted, num_deleted)
} else {
self.backend.apply_to_child_keys_while(child_info, |key| {
num_deleted = num_deleted.saturating_add(1);
self.overlay.set_child_storage(child_info, key.to_vec(), None);
true
});
true
(true, num_deleted)
}
}
@@ -1159,7 +1159,7 @@ mod tests {
changes_trie::disabled_state::<_, u64>(),
None,
);
assert_eq!(ext.kill_child_storage(&child_info, Some(2)), false);
assert_eq!(ext.kill_child_storage(&child_info, Some(2)), (false, 2));
}
assert_eq!(
@@ -1199,12 +1199,14 @@ mod tests {
changes_trie::disabled_state::<_, u64>(),
None,
);
assert_eq!(ext.kill_child_storage(&child_info, Some(0)), false);
assert_eq!(ext.kill_child_storage(&child_info, Some(1)), false);
assert_eq!(ext.kill_child_storage(&child_info, Some(2)), false);
assert_eq!(ext.kill_child_storage(&child_info, Some(3)), false);
assert_eq!(ext.kill_child_storage(&child_info, Some(4)), true);
assert_eq!(ext.kill_child_storage(&child_info, Some(5)), true);
assert_eq!(ext.kill_child_storage(&child_info, Some(0)), (false, 0));
assert_eq!(ext.kill_child_storage(&child_info, Some(1)), (false, 1));
assert_eq!(ext.kill_child_storage(&child_info, Some(2)), (false, 2));
assert_eq!(ext.kill_child_storage(&child_info, Some(3)), (false, 3));
assert_eq!(ext.kill_child_storage(&child_info, Some(4)), (true, 4));
// Only 4 items to remove
assert_eq!(ext.kill_child_storage(&child_info, Some(5)), (true, 4));
assert_eq!(ext.kill_child_storage(&child_info, None), (true, 4));
}
#[test]
@@ -132,7 +132,7 @@ impl<'a, H: Hasher, B: 'a + Backend<H>> Externalities for ReadOnlyExternalities<
&mut self,
_child_info: &ChildInfo,
_limit: Option<u32>,
) -> bool {
) -> (bool, u32) {
unimplemented!("kill_child_storage is not supported in ReadOnlyExternalities")
}
@@ -326,7 +326,7 @@ mod tests {
{
let mut ext = ext.ext();
assert!(!ext.kill_child_storage(&child_info, Some(2)), "Should not delete all keys");
assert!(!ext.kill_child_storage(&child_info, Some(2)).0, "Should not delete all keys");
assert!(ext.child_storage(&child_info, &b"doe"[..]).is_none());
assert!(ext.child_storage(&child_info, &b"dog"[..]).is_none());