From 9b8449de95f115c9554502f3442853dab88b0f26 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Wed, 10 Jul 2024 14:59:52 -0400 Subject: [PATCH] init --- .../storage/db/src/abstraction/cursor.rs | 196 ++++++++++++++++++ .../katana/storage/db/src/abstraction/mod.rs | 5 + .../storage/db/src/abstraction/transaction.rs | 52 +++++ crates/katana/storage/db/src/lib.rs | 1 + crates/katana/storage/db/src/mdbx/cursor.rs | 192 ++++------------- crates/katana/storage/db/src/mdbx/mod.rs | 4 +- crates/katana/storage/db/src/mdbx/tx.rs | 65 +++--- crates/katana/storage/db/src/tables.rs | 2 + .../storage/provider/src/providers/db/mod.rs | 1 + .../provider/src/providers/db/state.rs | 1 + 10 files changed, 331 insertions(+), 188 deletions(-) create mode 100644 crates/katana/storage/db/src/abstraction/cursor.rs create mode 100644 crates/katana/storage/db/src/abstraction/mod.rs create mode 100644 crates/katana/storage/db/src/abstraction/transaction.rs diff --git a/crates/katana/storage/db/src/abstraction/cursor.rs b/crates/katana/storage/db/src/abstraction/cursor.rs new file mode 100644 index 0000000000..252d4a9d30 --- /dev/null +++ b/crates/katana/storage/db/src/abstraction/cursor.rs @@ -0,0 +1,196 @@ +use crate::error::DatabaseError; +use crate::tables::{self, DupSort, Table}; +use crate::utils::KeyValue; + +/// Cursor trait for navigating the items within a database. +pub trait DbCursor: Sized { + /// Retrieves the first key/value pair, positioning the cursor at the first key/value pair in + /// the table. + fn first(&mut self) -> Result>, DatabaseError>; + + /// Retrieves key/value pair at current cursor position. + fn current(&mut self) -> Result>, DatabaseError>; + + /// Retrieves the next key/value pair, positioning the cursor at the next key/value pair in + /// the table. + fn next(&mut self) -> Result>, DatabaseError>; + + /// Retrieves the previous key/value pair, positioning the cursor at the previous key/value pair + /// in the table. + fn prev(&mut self) -> Result>, DatabaseError>; + + /// Retrieves the last key/value pair, positioning the cursor at the last key/value pair in + /// the table. + fn last(&mut self) -> Result>, DatabaseError>; + + /// Set the cursor to the specified key, returning and positioning the cursor at the item if + /// found. + fn set(&mut self, key: T::Key) -> Result>, DatabaseError>; + + /// Search for a `key` in a table, returning and positioning the cursor at the first item whose + /// key is greater than or equal to `key`. + fn seek(&mut self, key: T::Key) -> Result>, DatabaseError>; + + /// Creates a walker to iterate over the table items. + /// + /// If `start_key` is `None`, the walker will start at the first item of the table. Otherwise, + /// it will start at the first item whose key is greater than or equal to `start_key`. + fn walk(&mut self, start_key: Option) -> Result, DatabaseError>; +} + +/// Cursor trait for read-write operations. +pub trait DbCursorMut: DbCursor { + /// Database operation that will update an existing row if a specified value already + /// exists in a table, and insert a new row if the specified value doesn't already exist + fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>; + + /// Puts a key/value pair into the database. The cursor will be positioned at the new data item, + /// or on failure, usually near it. + fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>; + + /// Appends the data to the end of the table. Consequently, the append operation + /// will fail if the inserted key is less than the last table key + fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>; + + /// Deletes the current key/value pair. + fn delete_current(&mut self) -> Result<(), DatabaseError>; +} + +/// Cursor trait for DUPSORT tables. +pub trait DbDupSortCursor: DbCursor { + /// Positions the cursor at next data item of current key, returning the next `key-value` + /// pair of a DUPSORT table. + fn next_dup(&mut self) -> Result>, DatabaseError>; + + /// Similar to `next_dup()`, but instead of returning a `key-value` pair, it returns + /// only the `value`. + fn next_dup_val(&mut self) -> Result, DatabaseError>; + + /// Returns the next key/value pair skipping the duplicates. + fn next_no_dup(&mut self) -> Result>, DatabaseError>; + + /// Search for a `key` and `subkey` pair in a DUPSORT table. Positioning the cursor at the first + /// item whose `subkey` is greater than or equal to the specified `subkey`. + fn seek_by_key_subkey( + &mut self, + key: ::Key, + subkey: ::SubKey, + ) -> Result::Value>, DatabaseError>; + + /// Depending on its arguments, returns an iterator starting at: + /// - Some(key), Some(subkey): a `key` item whose data is >= than `subkey` + /// - Some(key), None: first item of a specified `key` + /// - None, Some(subkey): like first case, but in the first key + /// - None, None: first item in the table + /// of a DUPSORT table. + fn walk_dup( + &mut self, + key: Option, + subkey: Option<::SubKey>, + ) -> Result>, DatabaseError>; +} + +/// Cursor trait for read-write operations on DUPSORT tables. +pub trait DbDupSortCursorMut: DbDupSortCursor + DbCursorMut { + /// Deletes all values for the current key. + fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError>; + + /// Appends the data as a duplicate for the current key. + fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>; +} + +/// A key-value pair coming from an iterator. +/// +/// The `Result` represents that the operation might fail, while the `Option` represents whether or +/// not there is an entry. +pub type IterPairResult = Option, DatabaseError>>; + +/// Provides an iterator to a `Cursor` when handling `Table`. +#[derive(Debug)] +pub struct Walker<'c, T: Table, C: DbCursor> { + /// Cursor to be used to walk through the table. + cursor: &'c mut C, + /// Initial position of the dup walker. The value (key/value pair) where to start the walk. + start: IterPairResult, +} + +impl<'c, T, C> Walker<'c, T, C> +where + T: Table, + C: DbCursor, +{ + /// Create a new [`Walker`] from a [`Cursor`] and a [`IterPairResult`]. + pub fn new(cursor: &'c mut C, start: IterPairResult) -> Self { + Self { cursor, start } + } +} + +impl Walker<'_, T, C> +where + T: Table, + C: DbCursorMut, +{ + /// Delete the `key/value` pair item at the current position of the walker. + pub fn delete_current(&mut self) -> Result<(), DatabaseError> { + self.cursor.delete_current() + } +} + +impl std::iter::Iterator for Walker<'_, T, C> +where + T: Table, + C: DbCursor, +{ + type Item = Result, DatabaseError>; + fn next(&mut self) -> Option { + if let value @ Some(_) = self.start.take() { value } else { self.cursor.next().transpose() } + } +} + +/// A cursor iterator for `DUPSORT` table. +/// +/// Similar to [`Walker`], but for `DUPSORT` table. +#[derive(Debug)] +pub struct DupWalker<'c, T: Table, C: DbCursor> { + /// Cursor to be used to walk through the table. + cursor: &'c mut C, + /// Initial position of the dup walker. The value (key/value pair) where to start the walk. + start: IterPairResult, +} + +impl<'c, T, C> DupWalker<'c, T, C> +where + T: DupSort, + C: DbCursor, +{ + /// Creates a new [`DupWalker`] from a [`Cursor`] and a [`IterPairResult`]. + pub fn new(cursor: &'c mut C, start: IterPairResult) -> Self { + Self { cursor, start } + } +} + +impl DupWalker<'_, T, C> +where + T: DupSort, + C: DbCursorMut, +{ + /// Delete the item at the current position of the walker. + pub fn delete_current(&mut self) -> Result<(), DatabaseError> { + self.cursor.delete_current() + } +} + +impl std::iter::Iterator for DupWalker<'_, T, C> +where + T: DupSort, + C: DbDupSortCursor, +{ + type Item = Result, DatabaseError>; + fn next(&mut self) -> Option { + if let value @ Some(_) = self.start.take() { + value + } else { + self.cursor.next_dup().transpose() + } + } +} diff --git a/crates/katana/storage/db/src/abstraction/mod.rs b/crates/katana/storage/db/src/abstraction/mod.rs new file mode 100644 index 0000000000..f08f0896ad --- /dev/null +++ b/crates/katana/storage/db/src/abstraction/mod.rs @@ -0,0 +1,5 @@ +mod cursor; +mod transaction; + +pub use cursor::*; +pub use transaction::*; diff --git a/crates/katana/storage/db/src/abstraction/transaction.rs b/crates/katana/storage/db/src/abstraction/transaction.rs new file mode 100644 index 0000000000..e4b2640d23 --- /dev/null +++ b/crates/katana/storage/db/src/abstraction/transaction.rs @@ -0,0 +1,52 @@ +use super::cursor::{DbCursor, DbCursorMut}; +use crate::error::DatabaseError; +use crate::tables::Table; + +/// Trait for read-only transaction type. +pub trait DbTx { + /// The cursor type. + type Cursor: DbCursor; + + /// Creates a cursor to iterate over a table items. + fn cursor(&self) -> Result, DatabaseError>; + + /// Gets a value from a table using the given key. + fn get(&self, key: T::Key) -> Result, DatabaseError>; + + /// Returns number of entries in the table. + fn entries(&self) -> Result; + + /// Commits the transaction. + fn commit(self) -> Result; + + /// Aborts the transaction. + fn abort(self); +} + +/// Trait for read-write transaction type. +pub trait DbTxMut: DbTx { + /// The mutable cursor type. + type Cursor: DbCursorMut; + + /// Creates a cursor to mutably iterate over a table items. + fn cursor_mut(&self) -> Result<::Cursor, DatabaseError>; + + /// Inserts an item into a database. + /// + /// This function stores key/data pairs in the database. The default behavior is to enter the + /// new key/data pair, replacing any previously existing key if duplicates are disallowed, or + /// adding a duplicate data item if duplicates are allowed (DatabaseFlags::DUP_SORT). + fn put(&self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>; + + /// Delete items from a database, removing the key/data pair if it exists. + /// + /// If the data parameter is [Some] only the matching data item will be deleted. Otherwise, if + /// data parameter is [None], any/all value(s) for specified key will be deleted. + /// + /// Returns `true` if the key/value pair was present. + fn delete(&self, key: T::Key, value: Option) + -> Result; + + /// Clears all entries in the given database. This will empty the database. + fn clear(&self) -> Result<(), DatabaseError>; +} diff --git a/crates/katana/storage/db/src/lib.rs b/crates/katana/storage/db/src/lib.rs index 4d2642c168..14caf967c4 100644 --- a/crates/katana/storage/db/src/lib.rs +++ b/crates/katana/storage/db/src/lib.rs @@ -5,6 +5,7 @@ use std::path::Path; use anyhow::{anyhow, Context}; +pub mod abstraction; pub mod codecs; pub mod error; pub mod mdbx; diff --git a/crates/katana/storage/db/src/mdbx/cursor.rs b/crates/katana/storage/db/src/mdbx/cursor.rs index 9cac3876e3..890562d07c 100644 --- a/crates/katana/storage/db/src/mdbx/cursor.rs +++ b/crates/katana/storage/db/src/mdbx/cursor.rs @@ -5,6 +5,9 @@ use std::marker::PhantomData; use libmdbx::{self, TransactionKind, WriteFlags, RW}; +use crate::abstraction::{ + DbCursor, DbCursorMut, DbDupSortCursor, DbDupSortCursorMut, DupWalker, Walker, +}; use crate::codecs::{Compress, Encode}; use crate::error::DatabaseError; use crate::tables::{DupSort, Table}; @@ -32,54 +35,40 @@ impl Cursor { } } -impl Cursor { - /// Retrieves the first key/value pair, positioning the cursor at the first key/value pair in - /// the table. - pub fn first(&mut self) -> Result>, DatabaseError> { +impl DbCursor for Cursor +where + K: TransactionKind, + T: Table, +{ + fn first(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::first(&mut self.inner)) } - /// Retrieves key/value pair at current cursor position. - pub fn current(&mut self) -> Result>, DatabaseError> { + fn current(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::get_current(&mut self.inner)) } - /// Retrieves the next key/value pair, positioning the cursor at the next key/value pair in - /// the table. - #[allow(clippy::should_implement_trait)] - pub fn next(&mut self) -> Result>, DatabaseError> { + fn next(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::next(&mut self.inner)) } - /// Retrieves the previous key/value pair, positioning the cursor at the previous key/value pair - /// in the table. - pub fn prev(&mut self) -> Result>, DatabaseError> { + fn prev(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::prev(&mut self.inner)) } - /// Retrieves the last key/value pair, positioning the cursor at the last key/value pair in - /// the table. - pub fn last(&mut self) -> Result>, DatabaseError> { + fn last(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::last(&mut self.inner)) } - /// Set the cursor to the specified key, returning and positioning the cursor at the item if - /// found. - pub fn set(&mut self, key: ::Key) -> Result>, DatabaseError> { + fn set(&mut self, key: ::Key) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::set_key(&mut self.inner, key.encode().as_ref())) } - /// Search for a `key` in a table, returning and positioning the cursor at the first item whose - /// key is greater than or equal to `key`. - pub fn seek(&mut self, key: ::Key) -> Result>, DatabaseError> { + fn seek(&mut self, key: ::Key) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::set_range(&mut self.inner, key.encode().as_ref())) } - /// Creates a walker to iterate over the table items. - /// - /// If `start_key` is `None`, the walker will start at the first item of the table. Otherwise, - /// it will start at the first item whose key is greater than or equal to `start_key`. - pub fn walk(&mut self, start_key: Option) -> Result, DatabaseError> { + fn walk(&mut self, start_key: Option) -> Result, DatabaseError> { let start = if let Some(start_key) = start_key { self.inner .set_range(start_key.encode().as_ref()) @@ -93,30 +82,27 @@ impl Cursor { } } -impl Cursor { - /// Positions the cursor at next data item of current key, returning the next `key-value` - /// pair of a DUPSORT table. - pub fn next_dup(&mut self) -> Result>, DatabaseError> { +impl DbDupSortCursor for Cursor +where + K: TransactionKind, + T: DupSort, +{ + fn next_dup(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::next_dup(&mut self.inner)) } - /// Similar to [`Self::next_dup()`], but instead of returning a `key-value` pair, it returns - /// only the `value`. - pub fn next_dup_val(&mut self) -> Result::Value>, DatabaseError> { + fn next_dup_val(&mut self) -> Result::Value>, DatabaseError> { libmdbx::Cursor::next_dup(&mut self.inner) .map_err(DatabaseError::Read)? .map(decode_value::) .transpose() } - /// Returns the next key/value pair skipping the duplicates. - pub fn next_no_dup(&mut self) -> Result>, DatabaseError> { + fn next_no_dup(&mut self) -> Result>, DatabaseError> { decode!(libmdbx::Cursor::next_nodup(&mut self.inner)) } - /// Search for a `key` and `subkey` pair in a DUPSORT table. Positioning the cursor at the first - /// item whose `subkey` is greater than or equal to the specified `subkey`. - pub fn seek_by_key_subkey( + fn seek_by_key_subkey( &mut self, key: ::Key, subkey: ::SubKey, @@ -131,17 +117,11 @@ impl Cursor { .transpose() } - /// Depending on its arguments, returns an iterator starting at: - /// - Some(key), Some(subkey): a `key` item whose data is >= than `subkey` - /// - Some(key), None: first item of a specified `key` - /// - None, Some(subkey): like first case, but in the first key - /// - None, None: first item in the table - /// of a DUPSORT table. - pub fn walk_dup( + fn walk_dup( &mut self, key: Option, subkey: Option, - ) -> Result>, DatabaseError> { + ) -> Result>, DatabaseError> { let start = match (key, subkey) { (Some(key), Some(subkey)) => { // encode key and decode it after. @@ -186,15 +166,11 @@ impl Cursor { } } -impl Cursor { - /// Database operation that will update an existing row if a specified value already - /// exists in a table, and insert a new row if the specified value doesn't already exist - /// - /// For a `DUPSORT` table, `upsert` will not actually update-or-insert. If the key already - /// exists, it will append the value to the subkey, even if the subkeys are the same. So if - /// you want to properly upsert, you'll need to `seek_exact` & `delete_current` if the - /// key+subkey was found, before calling `upsert`. - pub fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { +impl DbCursorMut for Cursor +where + T: Table, +{ + fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { let key = Encode::encode(key); let value = Compress::compress(value); @@ -206,9 +182,7 @@ impl Cursor { }) } - /// Puts a key/value pair into the database. The cursor will be positioned at the new data item, - /// or on failure, usually near it. - pub fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { + fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { let key = Encode::encode(key); let value = Compress::compress(value); @@ -225,9 +199,7 @@ impl Cursor { }) } - /// Appends the data to the end of the table. Consequently, the append operation - /// will fail if the inserted key is less than the last table key - pub fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { + fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { let key = Encode::encode(key); let value = Compress::compress(value); @@ -239,23 +211,21 @@ impl Cursor { }) } - /// Deletes the current key/value pair. - pub fn delete_current(&mut self) -> Result<(), DatabaseError> { + fn delete_current(&mut self) -> Result<(), DatabaseError> { libmdbx::Cursor::del(&mut self.inner, WriteFlags::CURRENT).map_err(DatabaseError::Delete) } } -impl Cursor { - /// Deletes all values for the current key. - /// - /// This will delete all values for the current duplicate key of a `DUPSORT` table, including - /// the current item. - pub fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> { +impl DbDupSortCursorMut for Cursor +where + T: DupSort, +{ + fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> { libmdbx::Cursor::del(&mut self.inner, WriteFlags::NO_DUP_DATA) .map_err(DatabaseError::Delete) } - pub fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { + fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { let key = Encode::encode(key); let value = Compress::compress(value); @@ -267,83 +237,3 @@ impl Cursor { }) } } - -/// A key-value pair coming from an iterator. -/// -/// The `Result` represents that the operation might fail, while the `Option` represents whether or -/// not there is an entry. -pub type IterPairResult = Option, DatabaseError>>; - -/// Provides an iterator to a `Cursor` when handling `Table`. -#[derive(Debug)] -pub struct Walker<'c, K: TransactionKind, T: Table> { - /// Cursor to be used to walk through the table. - cursor: &'c mut Cursor, - /// Initial position of the dup walker. The value (key/value pair) where to start the walk. - start: IterPairResult, -} - -impl<'c, K, T> Walker<'c, K, T> -where - K: TransactionKind, - T: Table, -{ - /// Create a new [`Walker`] from a [`Cursor`] and a [`IterPairResult`]. - pub(super) fn new(cursor: &'c mut Cursor, start: IterPairResult) -> Self { - Self { cursor, start } - } -} - -impl Walker<'_, RW, T> { - /// Delete the `key/value` pair item at the current position of the walker. - pub fn delete_current(&mut self) -> Result<(), DatabaseError> { - self.cursor.delete_current() - } -} - -impl std::iter::Iterator for Walker<'_, K, T> { - type Item = Result, DatabaseError>; - fn next(&mut self) -> Option { - if let value @ Some(_) = self.start.take() { value } else { self.cursor.next().transpose() } - } -} - -/// A cursor iterator for `DUPSORT` table. -/// -/// Similar to [`Walker`], but for `DUPSORT` table. -#[derive(Debug)] -pub struct DupWalker<'c, K: TransactionKind, T: DupSort> { - /// Cursor to be used to walk through the table. - cursor: &'c mut Cursor, - /// Initial position of the dup walker. The value (key/value pair) where to start the walk. - start: IterPairResult, -} - -impl<'c, K, T> DupWalker<'c, K, T> -where - K: TransactionKind, - T: DupSort, -{ - /// Creates a new [`DupWalker`] from a [`Cursor`] and a [`IterPairResult`]. - pub(super) fn new(cursor: &'c mut Cursor, start: IterPairResult) -> Self { - Self { cursor, start } - } -} - -impl DupWalker<'_, RW, T> { - /// Delete the item at the current position of the walker. - pub fn delete_current(&mut self) -> Result<(), DatabaseError> { - self.cursor.delete_current() - } -} - -impl std::iter::Iterator for DupWalker<'_, K, T> { - type Item = Result, DatabaseError>; - fn next(&mut self) -> Option { - if let value @ Some(_) = self.start.take() { - value - } else { - self.cursor.next_dup().transpose() - } - } -} diff --git a/crates/katana/storage/db/src/mdbx/mod.rs b/crates/katana/storage/db/src/mdbx/mod.rs index 3b31ba0507..019aa3a5bc 100644 --- a/crates/katana/storage/db/src/mdbx/mod.rs +++ b/crates/katana/storage/db/src/mdbx/mod.rs @@ -7,9 +7,11 @@ pub mod tx; use std::path::Path; +pub use libmdbx; use libmdbx::{DatabaseFlags, EnvironmentFlags, Geometry, Mode, PageSize, SyncMode, RO, RW}; use self::tx::Tx; +use crate::abstraction::DbTx; use crate::error::DatabaseError; use crate::tables::{TableType, Tables}; use crate::utils; @@ -142,8 +144,8 @@ mod tests { use starknet::macros::felt; use super::*; + use crate::abstraction::{DbCursor, DbCursorMut, DbDupSortCursor, DbTxMut, Walker}; use crate::codecs::Encode; - use crate::mdbx::cursor::Walker; use crate::mdbx::test_utils::create_test_db; use crate::models::storage::StorageEntry; use crate::tables::{BlockHashes, ContractInfo, ContractStorage, Headers, Table}; diff --git a/crates/katana/storage/db/src/mdbx/tx.rs b/crates/katana/storage/db/src/mdbx/tx.rs index f1fbb37d77..bc2d0b3c35 100644 --- a/crates/katana/storage/db/src/mdbx/tx.rs +++ b/crates/katana/storage/db/src/mdbx/tx.rs @@ -7,6 +7,7 @@ use libmdbx::{TransactionKind, WriteFlags, RW}; use parking_lot::RwLock; use super::cursor::Cursor; +use crate::abstraction::{DbTx, DbTxMut}; use crate::codecs::{Compress, Encode}; use crate::error::DatabaseError; use crate::tables::{Table, Tables, NUM_TABLES}; @@ -34,15 +35,6 @@ impl Tx { Self { inner, db_handles: Default::default() } } - /// Creates a cursor to iterate over a table items. - pub fn cursor(&self) -> Result, DatabaseError> { - self.inner - .cursor_with_dbi(self.get_dbi::()?) - .map(Cursor::new) - .map_err(DatabaseError::CreateCursor) - } - - /// Gets a table database handle if it exists, otherwise creates it. pub fn get_dbi(&self) -> Result { let mut handles = self.db_handles.write(); let table = Tables::from_str(T::NAME).expect("requested table should be part of `Tables`."); @@ -55,9 +47,19 @@ impl Tx { Ok(dbi_handle.expect("is some; qed")) } +} + +impl DbTx for Tx { + type Cursor = Cursor; - /// Gets a value from a table using the given key. - pub fn get(&self, key: T::Key) -> Result::Value>, DatabaseError> { + fn cursor(&self) -> Result, DatabaseError> { + self.inner + .cursor_with_dbi(self.get_dbi::()?) + .map(Cursor::new) + .map_err(DatabaseError::CreateCursor) + } + + fn get(&self, key: T::Key) -> Result::Value>, DatabaseError> { let key = Encode::encode(key); self.inner .get(self.get_dbi::()?, key.as_ref()) @@ -66,40 +68,37 @@ impl Tx { .transpose() } - /// Returns number of entries in the table using cheap DB stats invocation. - pub fn entries(&self) -> Result { + fn entries(&self) -> Result { self.inner .db_stat_with_dbi(self.get_dbi::()?) .map(|stat| stat.entries()) .map_err(DatabaseError::Stat) } - /// Commits the transaction. - pub fn commit(self) -> Result { + fn commit(self) -> Result { self.inner.commit().map_err(DatabaseError::Commit) } + + fn abort(self) { + drop(self.inner) + } } -impl Tx { - /// Inserts an item into a database. - /// - /// This function stores key/data pairs in the database. The default behavior is to enter the - /// new key/data pair, replacing any previously existing key if duplicates are disallowed, or - /// adding a duplicate data item if duplicates are allowed (DatabaseFlags::DUP_SORT). - pub fn put(&self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { +impl DbTxMut for Tx { + type Cursor = Cursor; + + fn cursor_mut(&self) -> Result<::Cursor, DatabaseError> { + DbTx::cursor(self) + } + + fn put(&self, key: T::Key, value: T::Value) -> Result<(), DatabaseError> { let key = key.encode(); let value = value.compress(); self.inner.put(self.get_dbi::()?, key, value, WriteFlags::UPSERT).unwrap(); Ok(()) } - /// Delete items from a database, removing the key/data pair if it exists. - /// - /// If the data parameter is [Some] only the matching data item will be deleted. Otherwise, if - /// data parameter is [None], any/all value(s) for specified key will be deleted. - /// - /// Returns `true` if the key/value pair was present. - pub fn delete( + fn delete( &self, key: T::Key, value: Option, @@ -109,13 +108,7 @@ impl Tx { self.inner.del(self.get_dbi::()?, key.encode(), value).map_err(DatabaseError::Delete) } - /// Clears all entries in the given database. This will emtpy the database. - pub fn clear(&self) -> Result<(), DatabaseError> { + fn clear(&self) -> Result<(), DatabaseError> { self.inner.clear_db(self.get_dbi::()?).map_err(DatabaseError::Clear) } - - /// Aborts the transaction. - pub fn abort(self) { - drop(self.inner) - } } diff --git a/crates/katana/storage/db/src/tables.rs b/crates/katana/storage/db/src/tables.rs index d7af3e1333..380fb78f69 100644 --- a/crates/katana/storage/db/src/tables.rs +++ b/crates/katana/storage/db/src/tables.rs @@ -27,6 +27,8 @@ pub trait Table { type Value: Value; } +pub trait UniSort: Table {} + /// DupSort allows for keys to be repeated in the database. /// /// Upstream docs: diff --git a/crates/katana/storage/provider/src/providers/db/mod.rs b/crates/katana/storage/provider/src/providers/db/mod.rs index ec07fa213b..f3c18e6f1f 100644 --- a/crates/katana/storage/provider/src/providers/db/mod.rs +++ b/crates/katana/storage/provider/src/providers/db/mod.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::fmt::Debug; use std::ops::{Range, RangeInclusive}; +use katana_db::abstraction::{DbCursor, DbCursorMut, DbDupSortCursor, DbTx, DbTxMut}; use katana_db::error::DatabaseError; use katana_db::mdbx::{self, DbEnv}; use katana_db::models::block::StoredBlockBodyIndices; diff --git a/crates/katana/storage/provider/src/providers/db/state.rs b/crates/katana/storage/provider/src/providers/db/state.rs index d00db681b2..507a74c101 100644 --- a/crates/katana/storage/provider/src/providers/db/state.rs +++ b/crates/katana/storage/provider/src/providers/db/state.rs @@ -1,3 +1,4 @@ +use katana_db::abstraction::{DbCursorMut, DbDupSortCursor, DbTx, DbTxMut}; use katana_db::mdbx::{self}; use katana_db::models::contract::ContractInfoChangeList; use katana_db::models::list::BlockList;