diff --git a/storage/blockchain/README.md b/storage/blockchain/README.md index 2a7fc25..492c719 100644 --- a/storage/blockchain/README.md +++ b/storage/blockchain/README.md @@ -45,7 +45,7 @@ Failing to uphold these invariants may cause panics. # Examples The below is an example of using `cuprate_blockchain` lowest API, i.e. using a mix of this crate and `cuprate_database`'s traits directly - -this is not recommended. +**this is NOT recommended.** For examples of the higher-level APIs, see: - [`ops`] diff --git a/storage/blockchain/src/free.rs b/storage/blockchain/src/free.rs index 7e145a2..54003db 100644 --- a/storage/blockchain/src/free.rs +++ b/storage/blockchain/src/free.rs @@ -1,8 +1,61 @@ //! General free functions (related to the database). //---------------------------------------------------------------------------------------------------- Import +use cuprate_database::{ConcreteEnv, Env, EnvInner, InitError, RuntimeError, TxRw}; + +use crate::{config::Config, open_tables::OpenTables}; //---------------------------------------------------------------------------------------------------- Free functions +/// TODO +/// +/// # Errors +/// TODO +pub fn open(config: Config) -> Result { + // Attempt to open the database environment. + let env = ::open(config.db_config)?; + + /// Convert runtime errors to init errors. + /// + /// INVARIANT: + /// `cuprate_database`'s functions mostly return the former + /// so we must convert them. We have knowledge of which errors + /// makes sense in this functions context so we panic on + /// unexpected ones. + fn runtime_to_init_error(runtime: RuntimeError) -> InitError { + match runtime { + RuntimeError::Io(io_error) => io_error.into(), + + // These errors shouldn't be happening here. + RuntimeError::KeyExists + | RuntimeError::KeyNotFound + | RuntimeError::ResizeNeeded + | RuntimeError::TableNotFound => unreachable!(), + } + } + + // INVARIANT: We must ensure that all tables are created, + // `cuprate_database` has no way of knowing _which_ tables + // we want since it is agnostic, so we are responsible for this. + { + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw(); + let tx_rw = match tx_rw { + Ok(tx_rw) => tx_rw, + Err(e) => return Err(runtime_to_init_error(e)), + }; + + // Create all tables. + if let Err(e) = OpenTables::create_tables(&env_inner, &tx_rw) { + return Err(runtime_to_init_error(e)); + }; + + if let Err(e) = tx_rw.commit() { + return Err(runtime_to_init_error(e)); + } + } + + Ok(env) +} //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] diff --git a/storage/blockchain/src/lib.rs b/storage/blockchain/src/lib.rs index 1261c61..87e9ac9 100644 --- a/storage/blockchain/src/lib.rs +++ b/storage/blockchain/src/lib.rs @@ -114,7 +114,9 @@ pub use constants::{DATABASE_CORRUPT_MSG, DATABASE_VERSION}; mod open_tables; pub use open_tables::OpenTables; -pub mod free; +mod free; +pub use free::open; + pub mod ops; pub mod tables; pub mod types; diff --git a/storage/blockchain/src/open_tables.rs b/storage/blockchain/src/open_tables.rs index 0634ac4..5e3a9ae 100644 --- a/storage/blockchain/src/open_tables.rs +++ b/storage/blockchain/src/open_tables.rs @@ -41,6 +41,7 @@ macro_rules! call_fn_on_all_tables_or_early_return { )) }}; } +pub(crate) use call_fn_on_all_tables_or_early_return; //---------------------------------------------------------------------------------------------------- OpenTables /// TODO @@ -61,6 +62,12 @@ where /// # Errors /// TODO fn open_tables_mut(&'env self, tx_rw: &Rw) -> Result; + + /// TODO + /// + /// # Errors + /// TODO + fn create_tables(&'env self, tx_rw: &Rw) -> Result<(), RuntimeError>; } impl<'env, Ei, Ro, Rw> OpenTables<'env, Ro, Rw> for Ei @@ -80,6 +87,15 @@ where Self::open_db_rw(self, tx_rw) } } + + fn create_tables(&'env self, tx_rw: &Rw) -> Result<(), RuntimeError> { + match call_fn_on_all_tables_or_early_return! { + Self::create_db(self, tx_rw) + } { + Ok(_) => Ok(()), + Err(e) => Err(e), + } + } } //---------------------------------------------------------------------------------------------------- Tests