Storage: fix lifetimes (#215)
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled

* fix db lifetimes

* fix redb

* fix blockchain with redb

* add docs
This commit is contained in:
Boog900 2024-07-06 12:21:46 +00:00 committed by GitHub
parent d5c8eba1d8
commit a82c08cc80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 59 additions and 61 deletions

View file

@ -50,20 +50,12 @@ pub fn open(config: Config) -> Result<ConcreteEnv, InitError> {
// 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)),
};
let tx_rw = env_inner.tx_rw().map_err(runtime_to_init_error)?;
// Create all tables.
if let Err(e) = OpenTables::create_tables(&env_inner, &tx_rw) {
return Err(runtime_to_init_error(e));
};
OpenTables::create_tables(&env_inner, &tx_rw).map_err(runtime_to_init_error)?;
if let Err(e) = tx_rw.commit() {
return Err(runtime_to_init_error(e));
}
TxRw::commit(tx_rw).map_err(runtime_to_init_error)?;
}
Ok(env)

View file

@ -1,7 +1,7 @@
//! TODO
//---------------------------------------------------------------------------------------------------- Import
use cuprate_database::{EnvInner, RuntimeError, TxRo, TxRw};
use cuprate_database::{EnvInner, RuntimeError};
use crate::tables::{TablesIter, TablesMut};
@ -84,12 +84,12 @@ pub(crate) use call_fn_on_all_tables_or_early_return;
/// let mut tables = env_inner.open_tables_mut(&tx_rw)?;
/// # Ok(()) }
/// ```
pub trait OpenTables<'env, Ro, Rw>
where
Self: 'env,
Ro: TxRo<'env>,
Rw: TxRw<'env>,
{
pub trait OpenTables<'env> {
/// The read-only transaction type of the backend.
type Ro<'a>;
/// The read-write transaction type of the backend.
type Rw<'a>;
/// Open all tables in read/iter mode.
///
/// This calls [`EnvInner::open_db_ro`] on all database tables
@ -100,7 +100,7 @@ where
///
/// As all tables are created upon [`crate::open`],
/// this function will never error because a table doesn't exist.
fn open_tables(&'env self, tx_ro: &Ro) -> Result<impl TablesIter, RuntimeError>;
fn open_tables(&self, tx_ro: &Self::Ro<'_>) -> Result<impl TablesIter, RuntimeError>;
/// Open all tables in read-write mode.
///
@ -109,7 +109,7 @@ where
///
/// # Errors
/// This will only return [`RuntimeError::Io`] on errors.
fn open_tables_mut(&'env self, tx_rw: &Rw) -> Result<impl TablesMut, RuntimeError>;
fn open_tables_mut(&self, tx_rw: &Self::Rw<'_>) -> Result<impl TablesMut, RuntimeError>;
/// Create all database tables.
///
@ -118,28 +118,29 @@ where
///
/// # Errors
/// This will only return [`RuntimeError::Io`] on errors.
fn create_tables(&'env self, tx_rw: &Rw) -> Result<(), RuntimeError>;
fn create_tables(&self, tx_rw: &Self::Rw<'_>) -> Result<(), RuntimeError>;
}
impl<'env, Ei, Ro, Rw> OpenTables<'env, Ro, Rw> for Ei
impl<'env, Ei> OpenTables<'env> for Ei
where
Ei: EnvInner<'env, Ro, Rw>,
Ro: TxRo<'env>,
Rw: TxRw<'env>,
Ei: EnvInner<'env>,
{
fn open_tables(&'env self, tx_ro: &Ro) -> Result<impl TablesIter, RuntimeError> {
type Ro<'a> = <Ei as EnvInner<'env>>::Ro<'a>;
type Rw<'a> = <Ei as EnvInner<'env>>::Rw<'a>;
fn open_tables(&self, tx_ro: &Self::Ro<'_>) -> Result<impl TablesIter, RuntimeError> {
call_fn_on_all_tables_or_early_return! {
Self::open_db_ro(self, tx_ro)
}
}
fn open_tables_mut(&'env self, tx_rw: &Rw) -> Result<impl TablesMut, RuntimeError> {
fn open_tables_mut(&self, tx_rw: &Self::Rw<'_>) -> Result<impl TablesMut, RuntimeError> {
call_fn_on_all_tables_or_early_return! {
Self::open_db_rw(self, tx_rw)
}
}
fn create_tables(&'env self, tx_rw: &Rw) -> Result<(), RuntimeError> {
fn create_tables(&self, tx_rw: &Self::Rw<'_>) -> Result<(), RuntimeError> {
match call_fn_on_all_tables_or_early_return! {
Self::create_db(self, tx_rw)
} {

View file

@ -9,7 +9,7 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/storage/database"
keywords = ["cuprate", "database"]
[features]
default = ["heed"]
# default = ["heed"]
# default = ["redb"]
# default = ["redb-memory"]
heed = ["dep:heed"]

View file

@ -244,25 +244,28 @@ impl Env for ConcreteEnv {
}
//---------------------------------------------------------------------------------------------------- EnvInner Impl
impl<'env> EnvInner<'env, heed::RoTxn<'env>, RefCell<heed::RwTxn<'env>>>
for RwLockReadGuard<'env, heed::Env>
impl<'env> EnvInner<'env> for RwLockReadGuard<'env, heed::Env>
where
Self: 'env,
{
type Ro<'a> = heed::RoTxn<'a>;
type Rw<'a> = RefCell<heed::RwTxn<'a>>;
#[inline]
fn tx_ro(&'env self) -> Result<heed::RoTxn<'env>, RuntimeError> {
fn tx_ro(&self) -> Result<Self::Ro<'_>, RuntimeError> {
Ok(self.read_txn()?)
}
#[inline]
fn tx_rw(&'env self) -> Result<RefCell<heed::RwTxn<'env>>, RuntimeError> {
fn tx_rw(&self) -> Result<Self::Rw<'_>, RuntimeError> {
Ok(RefCell::new(self.write_txn()?))
}
#[inline]
fn open_db_ro<T: Table>(
&self,
tx_ro: &heed::RoTxn<'env>,
tx_ro: &Self::Ro<'_>,
) -> Result<impl DatabaseRo<T> + DatabaseIter<T>, RuntimeError> {
// Open up a read-only database using our table's const metadata.
//
@ -280,7 +283,7 @@ where
#[inline]
fn open_db_rw<T: Table>(
&self,
tx_rw: &RefCell<heed::RwTxn<'env>>,
tx_rw: &Self::Rw<'_>,
) -> Result<impl DatabaseRw<T>, RuntimeError> {
// Open up a read/write database using our table's const metadata.
//
@ -293,7 +296,7 @@ where
})
}
fn create_db<T: Table>(&self, tx_rw: &RefCell<heed::RwTxn<'env>>) -> Result<(), RuntimeError> {
fn create_db<T: Table>(&self, tx_rw: &Self::Rw<'_>) -> Result<(), RuntimeError> {
// Create a database using our:
// - [`Table`]'s const metadata.
// - (potentially) our [`Key`] comparison function
@ -325,10 +328,7 @@ where
}
#[inline]
fn clear_db<T: Table>(
&self,
tx_rw: &mut RefCell<heed::RwTxn<'env>>,
) -> Result<(), RuntimeError> {
fn clear_db<T: Table>(&self, tx_rw: &mut Self::Rw<'_>) -> Result<(), RuntimeError> {
let tx_rw = tx_rw.get_mut();
// Open the table. We don't care about flags or key

View file

@ -118,18 +118,20 @@ impl Env for ConcreteEnv {
}
//---------------------------------------------------------------------------------------------------- EnvInner Impl
impl<'env> EnvInner<'env, redb::ReadTransaction, redb::WriteTransaction>
for (&'env redb::Database, redb::Durability)
impl<'env> EnvInner<'env> for (&'env redb::Database, redb::Durability)
where
Self: 'env,
{
type Ro<'a> = redb::ReadTransaction;
type Rw<'a> = redb::WriteTransaction;
#[inline]
fn tx_ro(&'env self) -> Result<redb::ReadTransaction, RuntimeError> {
fn tx_ro(&self) -> Result<redb::ReadTransaction, RuntimeError> {
Ok(self.0.begin_read()?)
}
#[inline]
fn tx_rw(&'env self) -> Result<redb::WriteTransaction, RuntimeError> {
fn tx_rw(&self) -> Result<redb::WriteTransaction, RuntimeError> {
// `redb` has sync modes on the TX level, unlike heed,
// which sets it at the Environment level.
//
@ -142,7 +144,7 @@ where
#[inline]
fn open_db_ro<T: Table>(
&self,
tx_ro: &redb::ReadTransaction,
tx_ro: &Self::Ro<'_>,
) -> Result<impl DatabaseRo<T> + DatabaseIter<T>, RuntimeError> {
// Open up a read-only database using our `T: Table`'s const metadata.
let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> =
@ -154,7 +156,7 @@ where
#[inline]
fn open_db_rw<T: Table>(
&self,
tx_rw: &redb::WriteTransaction,
tx_rw: &Self::Rw<'_>,
) -> Result<impl DatabaseRw<T>, RuntimeError> {
// Open up a read/write database using our `T: Table`'s const metadata.
let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> =

View file

@ -62,17 +62,17 @@ pub trait Env: Sized {
// For `heed`, this is just `heed::Env`, for `redb` this is
// `(redb::Database, redb::Durability)` as each transaction
// needs the sync mode set during creation.
type EnvInner<'env>: EnvInner<'env, Self::TxRo<'env>, Self::TxRw<'env>>
type EnvInner<'env>: EnvInner<'env>
where
Self: 'env;
/// The read-only transaction type of the backend.
type TxRo<'env>: TxRo<'env> + 'env
type TxRo<'env>: TxRo<'env>
where
Self: 'env;
/// The read/write transaction type of the backend.
type TxRw<'env>: TxRw<'env> + 'env
type TxRw<'env>: TxRw<'env>
where
Self: 'env;
@ -209,23 +209,23 @@ Subsequent table opens will follow the flags/ordering, but only if
///
/// # Invariant
#[doc = doc_heed_create_db_invariant!()]
pub trait EnvInner<'env, Ro, Rw>
where
Self: 'env,
Ro: TxRo<'env>,
Rw: TxRw<'env>,
{
pub trait EnvInner<'env> {
/// The read-only transaction type of the backend.
type Ro<'a>: TxRo<'a>;
/// The read-write transaction type of the backend.
type Rw<'a>: TxRw<'a>;
/// Create a read-only transaction.
///
/// # Errors
/// This will only return [`RuntimeError::Io`] if it errors.
fn tx_ro(&'env self) -> Result<Ro, RuntimeError>;
fn tx_ro(&self) -> Result<Self::Ro<'_>, RuntimeError>;
/// Create a read/write transaction.
///
/// # Errors
/// This will only return [`RuntimeError::Io`] if it errors.
fn tx_rw(&'env self) -> Result<Rw, RuntimeError>;
fn tx_rw(&self) -> Result<Self::Rw<'_>, RuntimeError>;
/// Open a database in read-only mode.
///
@ -252,7 +252,7 @@ where
#[doc = doc_heed_create_db_invariant!()]
fn open_db_ro<T: Table>(
&self,
tx_ro: &Ro,
tx_ro: &Self::Ro<'_>,
) -> Result<impl DatabaseRo<T> + DatabaseIter<T>, RuntimeError>;
/// Open a database in read/write mode.
@ -271,7 +271,10 @@ where
///
/// # Invariant
#[doc = doc_heed_create_db_invariant!()]
fn open_db_rw<T: Table>(&self, tx_rw: &Rw) -> Result<impl DatabaseRw<T>, RuntimeError>;
fn open_db_rw<T: Table>(
&self,
tx_rw: &Self::Rw<'_>,
) -> Result<impl DatabaseRw<T>, RuntimeError>;
/// Create a database table.
///
@ -282,7 +285,7 @@ where
///
/// # Invariant
#[doc = doc_heed_create_db_invariant!()]
fn create_db<T: Table>(&self, tx_rw: &Rw) -> Result<(), RuntimeError>;
fn create_db<T: Table>(&self, tx_rw: &Self::Rw<'_>) -> Result<(), RuntimeError>;
/// Clear all `(key, value)`'s from a database table.
///
@ -297,5 +300,5 @@ where
///
/// If the specified table is not created upon before this function is called,
/// this will return [`RuntimeError::TableNotFound`].
fn clear_db<T: Table>(&self, tx_rw: &mut Rw) -> Result<(), RuntimeError>;
fn clear_db<T: Table>(&self, tx_rw: &mut Self::Rw<'_>) -> Result<(), RuntimeError>;
}