Skip to main content

reth_cli_commands/db/
settings.rs

1//! `reth db settings` command for managing storage settings
2
3use clap::{ArgAction, Parser, Subcommand};
4use reth_db_common::DbTool;
5use reth_provider::{
6    providers::ProviderNodeTypes, DBProvider, DatabaseProviderFactory, MetadataProvider,
7    MetadataWriter, StorageSettings,
8};
9
10use crate::common::AccessRights;
11
12/// `reth db settings` subcommand
13#[derive(Debug, Parser)]
14pub struct Command {
15    #[command(subcommand)]
16    command: Subcommands,
17}
18
19impl Command {
20    /// Returns database access rights required for the command.
21    pub fn access_rights(&self) -> AccessRights {
22        match self.command {
23            Subcommands::Get => AccessRights::RO,
24            Subcommands::Set(_) => AccessRights::RW,
25        }
26    }
27}
28
29#[derive(Debug, Clone, Copy, Subcommand)]
30enum Subcommands {
31    /// Get current storage settings from database
32    Get,
33    /// Set storage settings in database
34    #[clap(subcommand)]
35    Set(SetCommand),
36}
37
38/// Set storage settings
39#[derive(Debug, Clone, Copy, Subcommand)]
40#[clap(rename_all = "snake_case")]
41pub enum SetCommand {
42    /// Enable or disable v2 storage layout
43    ///
44    /// When enabled, uses static files for receipts/senders/changesets and RocksDB for
45    /// history indices and transaction hashes. When disabled, uses v1/legacy layout (everything in
46    /// MDBX).
47    V2 {
48        #[clap(action(ArgAction::Set))]
49        value: bool,
50    },
51}
52
53impl Command {
54    /// Execute the command
55    pub fn execute<N: ProviderNodeTypes>(self, tool: &DbTool<N>) -> eyre::Result<()> {
56        match self.command {
57            Subcommands::Get => self.get(tool),
58            Subcommands::Set(cmd) => self.set(cmd, tool),
59        }
60    }
61
62    fn get<N: ProviderNodeTypes>(&self, tool: &DbTool<N>) -> eyre::Result<()> {
63        // Read storage settings
64        let provider = tool.provider_factory.provider()?;
65        let storage_settings = provider.storage_settings()?;
66
67        // Display settings
68        match storage_settings {
69            Some(settings) => {
70                println!("Current storage settings:");
71                println!("{settings:#?}");
72            }
73            None => {
74                println!("No storage settings found.");
75            }
76        }
77
78        Ok(())
79    }
80
81    fn set<N: ProviderNodeTypes>(&self, cmd: SetCommand, tool: &DbTool<N>) -> eyre::Result<()> {
82        // Read storage settings
83        let provider_rw = tool.provider_factory.database_provider_rw()?;
84        // Destruct settings struct to not miss adding support for new fields
85        let settings = provider_rw.storage_settings()?;
86        if settings.is_none() {
87            println!("No storage settings found, creating new settings.");
88        }
89
90        let mut settings @ StorageSettings { storage_v2: _ } =
91            settings.unwrap_or_else(StorageSettings::v1);
92
93        // Update the setting based on the key
94        match cmd {
95            SetCommand::V2 { value } => {
96                if settings.storage_v2 == value {
97                    println!("storage_v2 is already set to {}", value);
98                    return Ok(());
99                }
100                settings.storage_v2 = value;
101                println!("Set storage_v2 = {}", value);
102            }
103        }
104
105        // Write updated settings
106        provider_rw.write_storage_settings(settings)?;
107        provider_rw.commit()?;
108
109        println!("Storage settings updated successfully.");
110
111        Ok(())
112    }
113}