reth_db/
mdbx.rs

1//! Helper functions for initializing and opening a database.
2
3use crate::{is_database_empty, TableSet, Tables};
4use eyre::Context;
5use std::path::Path;
6
7pub use crate::implementation::mdbx::*;
8pub use reth_libmdbx::*;
9
10/// Creates a new database at the specified path if it doesn't exist. Does NOT create tables. Check
11/// [`init_db`].
12pub fn create_db<P: AsRef<Path>>(path: P, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
13    use crate::version::{check_db_version_file, create_db_version_file, DatabaseVersionError};
14
15    let rpath = path.as_ref();
16    if is_database_empty(rpath) {
17        reth_fs_util::create_dir_all(rpath)
18            .wrap_err_with(|| format!("Could not create database directory {}", rpath.display()))?;
19        create_db_version_file(rpath)?;
20    } else {
21        match check_db_version_file(rpath) {
22            Ok(_) => (),
23            Err(DatabaseVersionError::MissingFile) => create_db_version_file(rpath)?,
24            Err(err) => return Err(err.into()),
25        }
26    }
27
28    Ok(DatabaseEnv::open(rpath, DatabaseEnvKind::RW, args)?)
29}
30
31/// Opens up an existing database or creates a new one at the specified path. Creates tables defined
32/// in [`Tables`] if necessary. Read/Write mode.
33pub fn init_db<P: AsRef<Path>>(path: P, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
34    init_db_for::<P, Tables>(path, args)
35}
36
37/// Opens up an existing database or creates a new one at the specified path. Creates tables defined
38/// in the given [`TableSet`] if necessary. Read/Write mode.
39pub fn init_db_for<P: AsRef<Path>, TS: TableSet>(
40    path: P,
41    args: DatabaseArguments,
42) -> eyre::Result<DatabaseEnv> {
43    let client_version = args.client_version().clone();
44    let db = create_db(path, args)?;
45    db.create_tables_for::<TS>()?;
46    db.record_client_version(client_version)?;
47    Ok(db)
48}
49
50/// Opens up an existing database. Read only mode. It doesn't create it or create tables if missing.
51pub fn open_db_read_only(
52    path: impl AsRef<Path>,
53    args: DatabaseArguments,
54) -> eyre::Result<DatabaseEnv> {
55    let path = path.as_ref();
56    DatabaseEnv::open(path, DatabaseEnvKind::RO, args)
57        .with_context(|| format!("Could not open database at path: {}", path.display()))
58}
59
60/// Opens up an existing database. Read/Write mode with `WriteMap` enabled. It doesn't create it or
61/// create tables if missing.
62pub fn open_db(path: impl AsRef<Path>, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
63    fn open(path: &Path, args: DatabaseArguments) -> eyre::Result<DatabaseEnv> {
64        let client_version = args.client_version().clone();
65        let db = DatabaseEnv::open(path, DatabaseEnvKind::RW, args)
66            .with_context(|| format!("Could not open database at path: {}", path.display()))?;
67        db.record_client_version(client_version)?;
68        Ok(db)
69    }
70    open(path.as_ref(), args)
71}