Skip to main content

reth_cli_commands/db/
copy.rs

1use clap::Parser;
2use reth_db::mdbx::{self, ffi};
3use std::path::PathBuf;
4
5/// Copies the MDBX database to a new location.
6///
7/// Equivalent to the standalone `mdbx_copy` tool but bundled into reth.
8#[derive(Parser, Debug)]
9pub struct Command {
10    /// Destination path for the database copy.
11    dest: PathBuf,
12
13    /// Compact the database while copying (reclaims free space).
14    #[arg(short, long)]
15    compact: bool,
16
17    /// Force dynamic size for the destination database.
18    #[arg(short = 'd', long)]
19    force_dynamic_size: bool,
20
21    /// Throttle to avoid MVCC pressure on writers.
22    #[arg(short = 'p', long)]
23    throttle_mvcc: bool,
24}
25
26impl Command {
27    /// Execute `db copy` command
28    pub fn execute(self, db: &mdbx::DatabaseEnv) -> eyre::Result<()> {
29        let mut flags: ffi::MDBX_copy_flags_t = ffi::MDBX_CP_DEFAULTS;
30        if self.compact {
31            flags |= ffi::MDBX_CP_COMPACT;
32        }
33        if self.force_dynamic_size {
34            flags |= ffi::MDBX_CP_FORCE_DYNAMIC_SIZE;
35        }
36        if self.throttle_mvcc {
37            flags |= ffi::MDBX_CP_THROTTLE_MVCC;
38        }
39
40        let dest = self
41            .dest
42            .to_str()
43            .ok_or_else(|| eyre::eyre!("destination path must be valid UTF-8"))?;
44        let dest_cstr = std::ffi::CString::new(dest)?;
45
46        println!("Copying database to {} ...", self.dest.display());
47
48        let rc = db.with_raw_env_ptr(|env_ptr| unsafe {
49            ffi::mdbx_env_copy(env_ptr, dest_cstr.as_ptr(), flags)
50        });
51
52        if rc != 0 {
53            eyre::bail!("mdbx_env_copy failed with error code {rc}: {}", unsafe {
54                std::ffi::CStr::from_ptr(ffi::mdbx_strerror(rc)).to_string_lossy()
55            });
56        }
57
58        println!("Done.");
59        Ok(())
60    }
61}