diff --git a/crates/cli/commands/src/db/copy.rs b/crates/cli/commands/src/db/copy.rs new file mode 100644 index 0000000000..075ce92229 --- /dev/null +++ b/crates/cli/commands/src/db/copy.rs @@ -0,0 +1,61 @@ +use clap::Parser; +use reth_db::mdbx::{self, ffi}; +use std::path::PathBuf; + +/// Copies the MDBX database to a new location. +/// +/// Equivalent to the standalone `mdbx_copy` tool but bundled into reth. +#[derive(Parser, Debug)] +pub struct Command { + /// Destination path for the database copy. + dest: PathBuf, + + /// Compact the database while copying (reclaims free space). + #[arg(short, long)] + compact: bool, + + /// Force dynamic size for the destination database. + #[arg(short = 'd', long)] + force_dynamic_size: bool, + + /// Throttle to avoid MVCC pressure on writers. + #[arg(short = 'p', long)] + throttle_mvcc: bool, +} + +impl Command { + /// Execute `db copy` command + pub fn execute(self, db: &mdbx::DatabaseEnv) -> eyre::Result<()> { + let mut flags: ffi::MDBX_copy_flags_t = ffi::MDBX_CP_DEFAULTS; + if self.compact { + flags |= ffi::MDBX_CP_COMPACT; + } + if self.force_dynamic_size { + flags |= ffi::MDBX_CP_FORCE_DYNAMIC_SIZE; + } + if self.throttle_mvcc { + flags |= ffi::MDBX_CP_THROTTLE_MVCC; + } + + let dest = self + .dest + .to_str() + .ok_or_else(|| eyre::eyre!("destination path must be valid UTF-8"))?; + let dest_cstr = std::ffi::CString::new(dest)?; + + println!("Copying database to {} ...", self.dest.display()); + + let rc = db.with_raw_env_ptr(|env_ptr| unsafe { + ffi::mdbx_env_copy(env_ptr, dest_cstr.as_ptr(), flags) + }); + + if rc != 0 { + eyre::bail!("mdbx_env_copy failed with error code {rc}: {}", unsafe { + std::ffi::CStr::from_ptr(ffi::mdbx_strerror(rc)).to_string_lossy() + }); + } + + println!("Done."); + Ok(()) + } +} diff --git a/crates/cli/commands/src/db/mod.rs b/crates/cli/commands/src/db/mod.rs index be21c05022..1676f2cb05 100644 --- a/crates/cli/commands/src/db/mod.rs +++ b/crates/cli/commands/src/db/mod.rs @@ -12,6 +12,7 @@ use std::{ mod account_storage; mod checksum; mod clear; +mod copy; mod diff; mod get; mod list; @@ -42,6 +43,8 @@ pub enum Subcommands { List(list::Command), /// Calculates the content checksum of a table or static file segment Checksum(checksum::Command), + /// Copies the MDBX database to a new location (bundled mdbx_copy) + Copy(copy::Command), /// Create a diff between two database tables or two entire databases. Diff(diff::Command), /// Gets the content of a table for the given key @@ -124,6 +127,11 @@ impl> Command command.execute(&tool)?; }); } + Subcommands::Copy(command) => { + db_exec!(self.env, tool, N, AccessRights::RO, { + command.execute(tool.provider_factory.db_ref())?; + }); + } Subcommands::Diff(command) => { db_exec!(self.env, tool, N, AccessRights::RO, { command.execute(&tool)?; diff --git a/docs/vocs/docs/pages/cli/SUMMARY.mdx b/docs/vocs/docs/pages/cli/SUMMARY.mdx index 9cc5586b55..28ceb9b2dc 100644 --- a/docs/vocs/docs/pages/cli/SUMMARY.mdx +++ b/docs/vocs/docs/pages/cli/SUMMARY.mdx @@ -13,6 +13,7 @@ - [`reth db checksum mdbx`](./reth/db/checksum/mdbx.mdx) - [`reth db checksum static-file`](./reth/db/checksum/static-file.mdx) - [`reth db checksum rocksdb`](./reth/db/checksum/rocksdb.mdx) + - [`reth db copy`](./reth/db/copy.mdx) - [`reth db diff`](./reth/db/diff.mdx) - [`reth db get`](./reth/db/get.mdx) - [`reth db get mdbx`](./reth/db/get/mdbx.mdx) diff --git a/docs/vocs/docs/pages/cli/reth/db.mdx b/docs/vocs/docs/pages/cli/reth/db.mdx index f8d8a70594..97e258b9e6 100644 --- a/docs/vocs/docs/pages/cli/reth/db.mdx +++ b/docs/vocs/docs/pages/cli/reth/db.mdx @@ -12,6 +12,7 @@ Commands: stats Lists all the tables, their entry count and their size list Lists the contents of a table checksum Calculates the content checksum of a table or static file segment + copy Copies the MDBX database to a new location (bundled mdbx_copy) diff Create a diff between two database tables or two entire databases get Gets the content of a table for the given key drop Deletes all database entries diff --git a/docs/vocs/docs/pages/cli/reth/db/copy.mdx b/docs/vocs/docs/pages/cli/reth/db/copy.mdx new file mode 100644 index 0000000000..ac81adf032 --- /dev/null +++ b/docs/vocs/docs/pages/cli/reth/db/copy.mdx @@ -0,0 +1,179 @@ +# reth db copy + +Copies the MDBX database to a new location (bundled mdbx_copy) + +```bash +$ reth db copy --help +``` +```txt +Usage: reth db copy [OPTIONS] + +Arguments: + + Destination path for the database copy + +Options: + -c, --compact + Compact the database while copying (reclaims free space) + + -d, --force-dynamic-size + Force dynamic size for the destination database + + -p, --throttle-mvcc + Throttle to avoid MVCC pressure on writers + + -h, --help + Print help (see a summary with '-h') + +Datadir: + --chain + The chain this node is running. + Possible values are either a built-in chain or the path to a chain specification file. + + Built-in chains: + mainnet, sepolia, holesky, hoodi, dev + + [default: mainnet] + +Logging: + --log.stdout.format + The format to use for logs written to stdout + + Possible values: + - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging + - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications + - terminal: Represents terminal-friendly formatting for logs + + [default: terminal] + + --log.stdout.filter + The filter to use for logs written to stdout + + [default: ] + + --log.file.format + The format to use for logs written to the log file + + Possible values: + - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging + - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications + - terminal: Represents terminal-friendly formatting for logs + + [default: terminal] + + --log.file.filter + The filter to use for logs written to the log file + + [default: debug] + + --log.file.directory + The path to put log files in + + [default: /logs] + + --log.file.name + The prefix name of the log files + + [default: reth.log] + + --log.file.max-size + The maximum size (in MB) of one log file + + [default: 200] + + --log.file.max-files + The maximum amount of log files that will be stored. If set to 0, background file logging is disabled + + [default: 5] + + --log.journald + Write logs to journald + + --log.journald.filter + The filter to use for logs written to journald + + [default: error] + + --color + Sets whether or not the formatter emits ANSI terminal escape codes for colors and other text formatting + + Possible values: + - always: Colors on + - auto: Auto-detect + - never: Colors off + + [default: always] + + --logs-otlp[=] + Enable `Opentelemetry` logs export to an OTLP endpoint. + + If no value provided, defaults based on protocol: - HTTP: `http://localhost:4318/v1/logs` - gRPC: `http://localhost:4317` + + Example: --logs-otlp=http://collector:4318/v1/logs + + [env: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=] + + --logs-otlp.filter + Set a filter directive for the OTLP logs exporter. This controls the verbosity of logs sent to the OTLP endpoint. It follows the same syntax as the `RUST_LOG` environment variable. + + Example: --logs-otlp.filter=info,reth=debug + + Defaults to INFO if not specified. + + [default: info] + +Display: + -v, --verbosity... + Set the minimum log level. + + -v Errors + -vv Warnings + -vvv Info + -vvvv Debug + -vvvvv Traces (warning: very verbose!) + + -q, --quiet + Silence all log output + +Tracing: + --tracing-otlp[=] + Enable `Opentelemetry` tracing export to an OTLP endpoint. + + If no value provided, defaults based on protocol: - HTTP: `http://localhost:4318/v1/traces` - gRPC: `http://localhost:4317` + + Example: --tracing-otlp=http://collector:4318/v1/traces + + [env: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=] + + --tracing-otlp-protocol + OTLP transport protocol to use for exporting traces and logs. + + - `http`: expects endpoint path to end with `/v1/traces` or `/v1/logs` - `grpc`: expects endpoint without a path + + Defaults to HTTP if not specified. + + Possible values: + - http: HTTP/Protobuf transport, port 4318, requires `/v1/traces` path + - grpc: gRPC transport, port 4317 + + [env: OTEL_EXPORTER_OTLP_PROTOCOL=] + [default: http] + + --tracing-otlp.filter + Set a filter directive for the OTLP tracer. This controls the verbosity of spans and events sent to the OTLP endpoint. It follows the same syntax as the `RUST_LOG` environment variable. + + Example: --tracing-otlp.filter=info,reth=debug,hyper_util=off + + Defaults to TRACE if not specified. + + [default: debug] + + --tracing-otlp.sample-ratio + Trace sampling ratio to control the percentage of traces to export. + + Valid range: 0.0 to 1.0 - 1.0, default: Sample all traces - 0.01: Sample 1% of traces - 0.0: Disable sampling + + Example: --tracing-otlp.sample-ratio=0.0. + + [env: OTEL_TRACES_SAMPLER_ARG=] +``` \ No newline at end of file diff --git a/docs/vocs/sidebar-cli-reth.ts b/docs/vocs/sidebar-cli-reth.ts index 6ef648ec01..3c5562a119 100644 --- a/docs/vocs/sidebar-cli-reth.ts +++ b/docs/vocs/sidebar-cli-reth.ts @@ -65,6 +65,10 @@ export const rethCliSidebar: SidebarItem = { } ] }, + { + text: "reth db copy", + link: "/cli/reth/db/copy" + }, { text: "reth db diff", link: "/cli/reth/db/diff"