Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move DbTool type to db-common #9119

Merged
merged 2 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ sha2 = { version = "0.10", default-features = false }
paste = "1.0"
url = "2.3"
backon = "0.4"
boyer-moore-magiclen = "0.2.16"

# metrics
metrics = "0.23.0"
Expand Down
1 change: 0 additions & 1 deletion bin/reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ backon.workspace = true
similar-asserts.workspace = true
itertools.workspace = true
rayon.workspace = true
boyer-moore-magiclen = "0.2.16"
ahash = "0.8"

# p2p
Expand Down
6 changes: 2 additions & 4 deletions bin/reth/src/commands/db/checksum.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use crate::{
commands::db::get::{maybe_json_value_parser, table_key},
utils::DbTool,
};
use crate::commands::db::get::{maybe_json_value_parser, table_key};
use ahash::RandomState;
use clap::Parser;
use reth_db::{DatabaseEnv, RawKey, RawTable, RawValue, TableViewer, Tables};
use reth_db_api::{cursor::DbCursorRO, database::Database, table::Table, transaction::DbTx};
use reth_db_common::DbTool;
use std::{
hash::{BuildHasher, Hasher},
sync::Arc,
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/db/diff.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{
args::DatabaseArgs,
dirs::{DataDirPath, PlatformPath},
utils::DbTool,
};
use clap::Parser;
use reth_db::{open_db_read_only, tables_to_generic, DatabaseEnv, Tables};
use reth_db_api::{cursor::DbCursorRO, database::Database, table::Table, transaction::DbTx};
use reth_db_common::DbTool;
use std::{
collections::HashMap,
fmt::Debug,
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/db/get.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::utils::DbTool;
use clap::Parser;
use reth_db::{
static_file::{ColumnSelectorOne, ColumnSelectorTwo, HeaderMask, ReceiptMask, TransactionMask},
Expand All @@ -8,6 +7,7 @@ use reth_db_api::{
database::Database,
table::{Decompress, DupSort, Table},
};
use reth_db_common::DbTool;
use reth_primitives::{BlockHash, Header};
use reth_provider::StaticFileProviderFactory;
use reth_static_file_types::StaticFileSegment;
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/db/list.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use super::tui::DbListTUI;
use crate::utils::{DbTool, ListFilter};
use clap::Parser;
use eyre::WrapErr;
use reth_db::{DatabaseEnv, RawValue, TableViewer, Tables};
use reth_db_api::{database::Database, table::Table};
use reth_db_common::{DbTool, ListFilter};
use reth_primitives::hex;
use std::{cell::RefCell, sync::Arc};
use tracing::error;
Expand Down
6 changes: 2 additions & 4 deletions bin/reth/src/commands/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
//! Database debugging tool

use crate::{
commands::common::{AccessRights, Environment, EnvironmentArgs},
utils::DbTool,
};
use crate::commands::common::{AccessRights, Environment, EnvironmentArgs};
use clap::{Parser, Subcommand};
use reth_db::version::{get_db_version, DatabaseVersionError, DB_VERSION};
use reth_db_common::DbTool;
use std::io::{self, Write};

mod checksum;
Expand Down
3 changes: 2 additions & 1 deletion bin/reth/src/commands/db/stats.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::{commands::db::checksum::ChecksumViewer, utils::DbTool};
use crate::commands::db::checksum::ChecksumViewer;
use clap::Parser;
use comfy_table::{Cell, Row, Table as ComfyTable};
use eyre::WrapErr;
use human_bytes::human_bytes;
use itertools::Itertools;
use reth_db::{mdbx, static_file::iter_static_files, DatabaseEnv, TableViewer, Tables};
use reth_db_api::database::Database;
use reth_db_common::DbTool;
use reth_fs_util as fs;
use reth_node_core::dirs::{ChainPath, DataDirPath};
use reth_provider::providers::StaticFileProvider;
Expand Down
6 changes: 4 additions & 2 deletions bin/reth/src/commands/stage/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
use crate::{
args::StageEnum,
commands::common::{AccessRights, Environment, EnvironmentArgs},
utils::DbTool,
};
use clap::Parser;
use itertools::Itertools;
use reth_db::{static_file::iter_static_files, tables, DatabaseEnv};
use reth_db_api::transaction::DbTxMut;
use reth_db_common::init::{insert_genesis_header, insert_genesis_history, insert_genesis_state};
use reth_db_common::{
init::{insert_genesis_header, insert_genesis_history, insert_genesis_state},
DbTool,
};
use reth_provider::{providers::StaticFileWriter, StaticFileProviderFactory};
use reth_stages::StageId;
use reth_static_file_types::{find_fixed_range, StaticFileSegment};
Expand Down
3 changes: 2 additions & 1 deletion bin/reth/src/commands/stage/dump/execution.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::setup;
use crate::{macros::block_executor, utils::DbTool};
use crate::macros::block_executor;
use reth_db::{tables, DatabaseEnv};
use reth_db_api::{
cursor::DbCursorRO, database::Database, table::TableImporter, transaction::DbTx,
};
use reth_db_common::DbTool;
use reth_node_core::dirs::{ChainPath, DataDirPath};
use reth_provider::{providers::StaticFileProvider, ChainSpecProvider, ProviderFactory};
use reth_stages::{stages::ExecutionStage, Stage, StageCheckpoint, UnwindInput};
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/stage/dump/hashing_account.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::setup;
use crate::utils::DbTool;
use eyre::Result;
use reth_db::{tables, DatabaseEnv};
use reth_db_api::{database::Database, table::TableImporter};
use reth_db_common::DbTool;
use reth_node_core::dirs::{ChainPath, DataDirPath};
use reth_primitives::BlockNumber;
use reth_provider::{providers::StaticFileProvider, ProviderFactory};
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/stage/dump/hashing_storage.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::setup;
use crate::utils::DbTool;
use eyre::Result;
use reth_db::{tables, DatabaseEnv};
use reth_db_api::{database::Database, table::TableImporter};
use reth_db_common::DbTool;
use reth_node_core::dirs::{ChainPath, DataDirPath};
use reth_provider::{providers::StaticFileProvider, ProviderFactory};
use reth_stages::{stages::StorageHashingStage, Stage, StageCheckpoint, UnwindInput};
Expand Down
3 changes: 2 additions & 1 deletion bin/reth/src/commands/stage/dump/merkle.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::setup;
use crate::{macros::block_executor, utils::DbTool};
use crate::macros::block_executor;
use eyre::Result;
use reth_config::config::EtlConfig;
use reth_db::{tables, DatabaseEnv};
use reth_db_api::{database::Database, table::TableImporter};
use reth_db_common::DbTool;
use reth_exex::ExExManagerHandle;
use reth_node_core::dirs::{ChainPath, DataDirPath};
use reth_primitives::BlockNumber;
Expand Down
5 changes: 2 additions & 3 deletions bin/reth/src/commands/stage/dump/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
//! Database debugging tool

use crate::{
args::DatadirArgs,
commands::common::{AccessRights, Environment, EnvironmentArgs},
dirs::DataDirPath,
utils::DbTool,
};

use crate::args::DatadirArgs;
use clap::Parser;
use reth_db::{init_db, mdbx::DatabaseArguments, tables, DatabaseEnv};
use reth_db_api::{
cursor::DbCursorRO, database::Database, models::ClientVersion, table::TableImporter,
transaction::DbTx,
};
use reth_db_common::DbTool;
use reth_node_core::dirs::PlatformPath;
use std::path::PathBuf;
use tracing::info;
Expand Down
188 changes: 0 additions & 188 deletions bin/reth/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
//! Common CLI utility functions.

use boyer_moore_magiclen::BMByte;
use eyre::Result;
use reth_chainspec::ChainSpec;
use reth_db::{RawTable, TableRawRow};
use reth_db_api::{
cursor::{DbCursorRO, DbDupCursorRO},
database::Database,
table::{Decode, Decompress, DupSort, Table, TableRow},
transaction::{DbTx, DbTxMut},
DatabaseError,
};
use reth_fs_util as fs;
use reth_provider::{ChainSpecProvider, ProviderFactory};
use std::{path::Path, rc::Rc, sync::Arc};
use tracing::info;

/// Exposing `open_db_read_only` function
pub mod db {
pub use reth_db::open_db_read_only;
Expand All @@ -24,175 +8,3 @@ pub mod db {
/// Re-exported from `reth_node_core`, also to prevent a breaking change. See the comment on
/// the `reth_node_core::args` re-export for more details.
pub use reth_node_core::utils::*;

/// Wrapper over DB that implements many useful DB queries.
#[derive(Debug)]
pub struct DbTool<DB: Database> {
/// The provider factory that the db tool will use.
pub provider_factory: ProviderFactory<DB>,
}

impl<DB: Database> DbTool<DB> {
/// Takes a DB where the tables have already been created.
pub fn new(provider_factory: ProviderFactory<DB>) -> eyre::Result<Self> {
// Disable timeout because we are entering a TUI which might read for a long time. We
// disable on the [`DbTool`] level since it's only used in the CLI.
provider_factory.provider()?.disable_long_read_transaction_safety();
Ok(Self { provider_factory })
}

/// Get an [`Arc`] to the [`ChainSpec`].
pub fn chain(&self) -> Arc<ChainSpec> {
self.provider_factory.chain_spec()
}

/// Grabs the contents of the table within a certain index range and places the
/// entries into a [`HashMap`][std::collections::HashMap].
///
/// [`ListFilter`] can be used to further
/// filter down the desired results. (eg. List only rows which include `0xd3adbeef`)
pub fn list<T: Table>(&self, filter: &ListFilter) -> Result<(Vec<TableRow<T>>, usize)> {
let bmb = Rc::new(BMByte::from(&filter.search));
if bmb.is_none() && filter.has_search() {
eyre::bail!("Invalid search.")
}

let mut hits = 0;

let data = self.provider_factory.db_ref().view(|tx| {
let mut cursor =
tx.cursor_read::<RawTable<T>>().expect("Was not able to obtain a cursor.");

let map_filter = |row: Result<TableRawRow<T>, _>| {
if let Ok((k, v)) = row {
let (key, value) = (k.into_key(), v.into_value());

if key.len() + value.len() < filter.min_row_size {
return None
}
if key.len() < filter.min_key_size {
return None
}
if value.len() < filter.min_value_size {
return None
}

let result = || {
if filter.only_count {
return None
}
Some((
<T as Table>::Key::decode(&key).unwrap(),
<T as Table>::Value::decompress(&value).unwrap(),
))
};

match &*bmb {
Some(searcher) => {
if searcher.find_first_in(&value).is_some() ||
searcher.find_first_in(&key).is_some()
{
hits += 1;
return result()
}
}
None => {
hits += 1;
return result()
}
}
}
None
};

if filter.reverse {
Ok(cursor
.walk_back(None)?
.skip(filter.skip)
.filter_map(map_filter)
.take(filter.len)
.collect::<Vec<(_, _)>>())
} else {
Ok(cursor
.walk(None)?
.skip(filter.skip)
.filter_map(map_filter)
.take(filter.len)
.collect::<Vec<(_, _)>>())
}
})?;

Ok((data.map_err(|e: DatabaseError| eyre::eyre!(e))?, hits))
}

/// Grabs the content of the table for the given key
pub fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>> {
self.provider_factory.db_ref().view(|tx| tx.get::<T>(key))?.map_err(|e| eyre::eyre!(e))
}

/// Grabs the content of the `DupSort` table for the given key and subkey
pub fn get_dup<T: DupSort>(&self, key: T::Key, subkey: T::SubKey) -> Result<Option<T::Value>> {
self.provider_factory
.db_ref()
.view(|tx| tx.cursor_dup_read::<T>()?.seek_by_key_subkey(key, subkey))?
.map_err(|e| eyre::eyre!(e))
}

/// Drops the database and the static files at the given path.
pub fn drop(
&self,
db_path: impl AsRef<Path>,
static_files_path: impl AsRef<Path>,
) -> Result<()> {
let db_path = db_path.as_ref();
info!(target: "reth::cli", "Dropping database at {:?}", db_path);
fs::remove_dir_all(db_path)?;

let static_files_path = static_files_path.as_ref();
info!(target: "reth::cli", "Dropping static files at {:?}", static_files_path);
fs::remove_dir_all(static_files_path)?;
fs::create_dir_all(static_files_path)?;

Ok(())
}

/// Drops the provided table from the database.
pub fn drop_table<T: Table>(&self) -> Result<()> {
self.provider_factory.db_ref().update(|tx| tx.clear::<T>())??;
Ok(())
}
}

/// Filters the results coming from the database.
#[derive(Debug)]
pub struct ListFilter {
/// Skip first N entries.
pub skip: usize,
/// Take N entries.
pub len: usize,
/// Sequence of bytes that will be searched on values and keys from the database.
pub search: Vec<u8>,
/// Minimum row size.
pub min_row_size: usize,
/// Minimum key size.
pub min_key_size: usize,
/// Minimum value size.
pub min_value_size: usize,
/// Reverse order of entries.
pub reverse: bool,
/// Only counts the number of filtered entries without decoding and returning them.
pub only_count: bool,
}

impl ListFilter {
/// If `search` has a list of bytes, then filter for rows that have this sequence.
pub fn has_search(&self) -> bool {
!self.search.is_empty()
}

/// Updates the page with new `skip` and `len` values.
pub fn update_page(&mut self, skip: usize, len: usize) {
self.skip = skip;
self.len = len;
}
}
Loading
Loading