reth_db_api/
unwind.rs
1use crate::{cursor::DbCursorRO, table::Table, transaction::DbTxMut};
2use reth_storage_errors::db::DatabaseError;
3use std::ops::RangeBounds;
4
5pub trait DbTxUnwindExt: DbTxMut {
7 #[inline]
12 fn unwind_table_by_num<T>(&self, num: u64) -> Result<usize, DatabaseError>
13 where
14 T: Table<Key = u64>,
15 {
16 self.unwind_table::<T, _>(num, |key| key)
17 }
18
19 fn unwind_table<T, F>(&self, key: u64, mut selector: F) -> Result<usize, DatabaseError>
24 where
25 T: Table,
26 F: FnMut(T::Key) -> u64,
27 {
28 let mut cursor = self.cursor_write::<T>()?;
29 let mut reverse_walker = cursor.walk_back(None)?;
30 let mut deleted = 0;
31
32 while let Some(Ok((entry_key, _))) = reverse_walker.next() {
33 if selector(entry_key.clone()) <= key {
34 break
35 }
36 reverse_walker.delete_current()?;
37 deleted += 1;
38 }
39
40 Ok(deleted)
41 }
42
43 fn unwind_table_by_walker<T1, T2>(
47 &self,
48 range: impl RangeBounds<T1::Key>,
49 ) -> Result<(), DatabaseError>
50 where
51 T1: Table,
52 T2: Table<Key = T1::Value>,
53 {
54 let mut cursor = self.cursor_write::<T1>()?;
55 let mut walker = cursor.walk_range(range)?;
56 while let Some((_, value)) = walker.next().transpose()? {
57 self.delete::<T2>(value, None)?;
58 }
59 Ok(())
60 }
61}
62
63impl<T> DbTxUnwindExt for T where T: DbTxMut {}