mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
refactor(cli): db subcommands (#19754)
This commit is contained in:
@@ -6,8 +6,9 @@ use reth_db_api::{
|
||||
transaction::{DbTx, DbTxMut},
|
||||
TableViewer, Tables,
|
||||
};
|
||||
use reth_db_common::DbTool;
|
||||
use reth_node_builder::NodeTypesWithDB;
|
||||
use reth_provider::{ProviderFactory, StaticFileProviderFactory};
|
||||
use reth_provider::StaticFileProviderFactory;
|
||||
use reth_static_file_types::StaticFileSegment;
|
||||
|
||||
/// The arguments for the `reth db clear` command
|
||||
@@ -19,16 +20,13 @@ pub struct Command {
|
||||
|
||||
impl Command {
|
||||
/// Execute `db clear` command
|
||||
pub fn execute<N: NodeTypesWithDB>(
|
||||
self,
|
||||
provider_factory: ProviderFactory<N>,
|
||||
) -> eyre::Result<()> {
|
||||
pub fn execute<N: NodeTypesWithDB>(self, tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
match self.subcommand {
|
||||
Subcommands::Mdbx { table } => {
|
||||
table.view(&ClearViewer { db: provider_factory.db_ref() })?
|
||||
table.view(&ClearViewer { db: tool.provider_factory.db_ref() })?
|
||||
}
|
||||
Subcommands::StaticFile { segment } => {
|
||||
let static_file_provider = provider_factory.static_file_provider();
|
||||
let static_file_provider = tool.provider_factory.static_file_provider();
|
||||
let static_files = iter_static_files(static_file_provider.directory())?;
|
||||
|
||||
if let Some(segment_static_files) = static_files.get(&segment) {
|
||||
|
||||
@@ -60,10 +60,11 @@ pub enum Subcommands {
|
||||
Path,
|
||||
}
|
||||
|
||||
/// `db_ro_exec` opens a database in read-only mode, and then execute with the provided command
|
||||
macro_rules! db_ro_exec {
|
||||
($env:expr, $tool:ident, $N:ident, $command:block) => {
|
||||
let Environment { provider_factory, .. } = $env.init::<$N>(AccessRights::RO)?;
|
||||
/// Initializes a provider factory with specified access rights, and then execute with the provided
|
||||
/// command
|
||||
macro_rules! db_exec {
|
||||
($env:expr, $tool:ident, $N:ident, $access_rights:expr, $command:block) => {
|
||||
let Environment { provider_factory, .. } = $env.init::<$N>($access_rights)?;
|
||||
|
||||
let $tool = DbTool::new(provider_factory)?;
|
||||
$command;
|
||||
@@ -91,27 +92,32 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Command<C>
|
||||
match self.command {
|
||||
// TODO: We'll need to add this on the DB trait.
|
||||
Subcommands::Stats(command) => {
|
||||
db_ro_exec!(self.env, tool, N, {
|
||||
let access_rights = if command.skip_consistency_checks {
|
||||
AccessRights::RoInconsistent
|
||||
} else {
|
||||
AccessRights::RO
|
||||
};
|
||||
db_exec!(self.env, tool, N, access_rights, {
|
||||
command.execute(data_dir, &tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::List(command) => {
|
||||
db_ro_exec!(self.env, tool, N, {
|
||||
db_exec!(self.env, tool, N, AccessRights::RO, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::Checksum(command) => {
|
||||
db_ro_exec!(self.env, tool, N, {
|
||||
db_exec!(self.env, tool, N, AccessRights::RO, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::Diff(command) => {
|
||||
db_ro_exec!(self.env, tool, N, {
|
||||
db_exec!(self.env, tool, N, AccessRights::RO, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::Get(command) => {
|
||||
db_ro_exec!(self.env, tool, N, {
|
||||
db_exec!(self.env, tool, N, AccessRights::RO, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
@@ -133,21 +139,27 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Command<C>
|
||||
}
|
||||
}
|
||||
|
||||
let Environment { provider_factory, .. } = self.env.init::<N>(AccessRights::RW)?;
|
||||
let tool = DbTool::new(provider_factory)?;
|
||||
tool.drop(db_path, static_files_path, exex_wal_path)?;
|
||||
db_exec!(self.env, tool, N, AccessRights::RW, {
|
||||
tool.drop(db_path, static_files_path, exex_wal_path)?;
|
||||
});
|
||||
}
|
||||
Subcommands::Clear(command) => {
|
||||
let Environment { provider_factory, .. } = self.env.init::<N>(AccessRights::RW)?;
|
||||
command.execute(provider_factory)?;
|
||||
db_exec!(self.env, tool, N, AccessRights::RW, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::RepairTrie(command) => {
|
||||
let access_rights =
|
||||
if command.dry_run { AccessRights::RO } else { AccessRights::RW };
|
||||
let Environment { provider_factory, .. } = self.env.init::<N>(access_rights)?;
|
||||
command.execute(provider_factory)?;
|
||||
db_exec!(self.env, tool, N, access_rights, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::StaticFileHeader(command) => {
|
||||
db_exec!(self.env, tool, N, AccessRights::RoInconsistent, {
|
||||
command.execute(&tool)?;
|
||||
});
|
||||
}
|
||||
Subcommands::StaticFileHeader(command) => command.execute::<N, _>(self.env)?,
|
||||
Subcommands::Version => {
|
||||
let local_db_version = match get_db_version(&db_path) {
|
||||
Ok(version) => Some(version),
|
||||
|
||||
@@ -5,8 +5,9 @@ use reth_db_api::{
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_db_common::DbTool;
|
||||
use reth_node_builder::NodeTypesWithDB;
|
||||
use reth_provider::{providers::ProviderNodeTypes, ProviderFactory, StageCheckpointReader};
|
||||
use reth_provider::{providers::ProviderNodeTypes, StageCheckpointReader};
|
||||
use reth_stages::StageId;
|
||||
use reth_trie::{
|
||||
verify::{Output, Verifier},
|
||||
@@ -29,23 +30,20 @@ pub struct Command {
|
||||
|
||||
impl Command {
|
||||
/// Execute `db repair-trie` command
|
||||
pub fn execute<N: ProviderNodeTypes>(
|
||||
self,
|
||||
provider_factory: ProviderFactory<N>,
|
||||
) -> eyre::Result<()> {
|
||||
pub fn execute<N: ProviderNodeTypes>(self, tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
if self.dry_run {
|
||||
verify_only(provider_factory)?
|
||||
verify_only(tool)?
|
||||
} else {
|
||||
verify_and_repair(provider_factory)?
|
||||
verify_and_repair(tool)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_only<N: NodeTypesWithDB>(provider_factory: ProviderFactory<N>) -> eyre::Result<()> {
|
||||
fn verify_only<N: NodeTypesWithDB>(tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
// Get a database transaction directly from the database
|
||||
let db = provider_factory.db_ref();
|
||||
let db = tool.provider_factory.db_ref();
|
||||
let mut tx = db.tx()?;
|
||||
tx.disable_long_read_transaction_safety();
|
||||
|
||||
@@ -114,11 +112,9 @@ fn verify_checkpoints(provider: impl StageCheckpointReader) -> eyre::Result<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_and_repair<N: ProviderNodeTypes>(
|
||||
provider_factory: ProviderFactory<N>,
|
||||
) -> eyre::Result<()> {
|
||||
fn verify_and_repair<N: ProviderNodeTypes>(tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
// Get a read-write database provider
|
||||
let mut provider_rw = provider_factory.provider_rw()?;
|
||||
let mut provider_rw = tool.provider_factory.provider_rw()?;
|
||||
|
||||
// Check that a pipeline sync isn't in progress.
|
||||
verify_checkpoints(provider_rw.as_ref())?;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use reth_cli::chainspec::ChainSpecParser;
|
||||
use reth_provider::StaticFileProviderFactory;
|
||||
use reth_db_common::DbTool;
|
||||
use reth_provider::{providers::ProviderNodeTypes, StaticFileProviderFactory};
|
||||
use reth_static_file_types::StaticFileSegment;
|
||||
use std::path::PathBuf;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::common::{AccessRights, CliNodeTypes, EnvironmentArgs};
|
||||
|
||||
/// The arguments for the `reth db static-file-header` command
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Command {
|
||||
@@ -34,21 +32,12 @@ enum Source {
|
||||
|
||||
impl Command {
|
||||
/// Execute `db static-file-header` command
|
||||
pub fn execute<N: CliNodeTypes, C: ChainSpecParser<ChainSpec = N::ChainSpec>>(
|
||||
self,
|
||||
env: EnvironmentArgs<C>,
|
||||
) -> eyre::Result<()> {
|
||||
// Try to initialize the environment as read-only. If it fails, try to initialize it as
|
||||
// read-only without consistency checks.
|
||||
let provider_factory = match env.init::<N>(AccessRights::RO) {
|
||||
Ok(env) => env,
|
||||
Err(err) => {
|
||||
warn!(?err, "Failed to initialize environment");
|
||||
env.init::<N>(AccessRights::RoInconsistent)?
|
||||
}
|
||||
pub fn execute<N: ProviderNodeTypes>(self, tool: &DbTool<N>) -> eyre::Result<()> {
|
||||
let static_file_provider = tool.provider_factory.static_file_provider();
|
||||
if let Err(err) = static_file_provider.check_consistency(&tool.provider_factory.provider()?)
|
||||
{
|
||||
warn!("Error checking consistency of static files: {err}");
|
||||
}
|
||||
.provider_factory;
|
||||
let static_file_provider = provider_factory.static_file_provider();
|
||||
|
||||
// Get the provider based on the source
|
||||
let provider = match self.source {
|
||||
|
||||
@@ -18,6 +18,10 @@ use std::{sync::Arc, time::Duration};
|
||||
#[derive(Parser, Debug)]
|
||||
/// The arguments for the `reth db stats` command
|
||||
pub struct Command {
|
||||
/// Skip consistency checks for static files.
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub(crate) skip_consistency_checks: bool,
|
||||
|
||||
/// Show only the total size for static files.
|
||||
#[arg(long, default_value_t = false)]
|
||||
detailed_sizes: bool,
|
||||
|
||||
@@ -9,6 +9,9 @@ $ reth db stats --help
|
||||
Usage: reth db stats [OPTIONS]
|
||||
|
||||
Options:
|
||||
--skip-consistency-checks
|
||||
Skip consistency checks for static files
|
||||
|
||||
--detailed-sizes
|
||||
Show only the total size for static files
|
||||
|
||||
|
||||
Reference in New Issue
Block a user