1use crate::{is_database_empty, TableSet, Tables};
4use eyre::Context;
5use reth_tracing::tracing::info;
6use std::path::Path;
7
8pub use crate::implementation::mdbx::*;
9pub use reth_libmdbx::*;
10
11const ORPHAN_TABLES: &[&str] = &["AccountsTrieChangeSets", "StoragesTrieChangeSets"];
14
15pub fn create_db<P: AsRef<Path>>(path: P, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
18 use crate::version::{check_db_version_file, create_db_version_file, DatabaseVersionError};
19
20 let rpath = path.as_ref();
21 if is_database_empty(rpath) {
22 reth_fs_util::create_dir_all(rpath)
23 .wrap_err_with(|| format!("Could not create database directory {}", rpath.display()))?;
24 create_db_version_file(rpath)?;
25 } else {
26 match check_db_version_file(rpath) {
27 Ok(_) => (),
28 Err(DatabaseVersionError::MissingFile) => create_db_version_file(rpath)?,
29 Err(err) => return Err(err.into()),
30 }
31 }
32
33 Ok(DatabaseEnv::open(rpath, DatabaseEnvKind::RW, args)?)
34}
35
36pub fn init_db<P: AsRef<Path>>(path: P, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
39 init_db_for::<P, Tables>(path, args)
40}
41
42pub fn init_db_for<P: AsRef<Path>, TS: TableSet>(
45 path: P,
46 args: DatabaseArguments,
47) -> eyre::Result<DatabaseEnv> {
48 let client_version = args.client_version().clone();
49 let mut db = create_db(path, args)?;
50 db.create_and_track_tables_for::<TS>()?;
51 db.record_client_version(client_version)?;
52 drop_orphan_tables(&db);
53 Ok(db)
54}
55
56fn drop_orphan_tables(db: &DatabaseEnv) {
58 for table_name in ORPHAN_TABLES {
59 match db.drop_orphan_table(table_name) {
60 Ok(true) => {
61 info!(target: "reth::db", table = %table_name, "Dropped orphaned database table");
62 }
63 Ok(false) => {}
64 Err(e) => {
65 reth_tracing::tracing::warn!(
66 target: "reth::db",
67 table = %table_name,
68 %e,
69 "Failed to drop orphaned database table"
70 );
71 }
72 }
73 }
74}
75
76pub fn open_db_read_only(
78 path: impl AsRef<Path>,
79 args: DatabaseArguments,
80) -> eyre::Result<DatabaseEnv> {
81 let path = path.as_ref();
82 DatabaseEnv::open(path, DatabaseEnvKind::RO, args)
83 .with_context(|| format!("Could not open database at path: {}", path.display()))
84}
85
86pub fn open_db(path: impl AsRef<Path>, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
89 fn open(path: &Path, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
90 let client_version = args.client_version().clone();
91 let db = DatabaseEnv::open(path, DatabaseEnvKind::RW, args)
92 .with_context(|| format!("Could not open database at path: {}", path.display()))?;
93 db.record_client_version(client_version)?;
94 Ok(db)
95 }
96 open(path.as_ref(), args)
97}