database: redb 1.5.0 -> redb 2.0.0 (#95)

* `redb 1.5.0` -> `redb 2.0.0`

* `Redb{Key,Value}` -> `redb::{Key,Value}`

* redb: remove unneeded lifetimes

* database: remove read table lifetime

* redb: remove read table lifetime

* heed: remove `'tx` lifetime on read table

* remove `'env, 'tx` lifetime from read/write table

* redb: remove `'env, 'tx` lifetime from read/write table

* heed: remove `'env, 'tx` lifetime from read/write table

* redb: update `TxRo::commit()` docs
This commit is contained in:
hinto-janai 2024-03-24 18:15:26 -04:00 committed by GitHub
parent 3656a1ada7
commit 5e7ee57482
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 73 additions and 79 deletions

4
Cargo.lock generated
View file

@ -2188,9 +2188,9 @@ dependencies = [
[[package]] [[package]]
name = "redb" name = "redb"
version = "1.5.0" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72623e6275cd430215b741f41ebda34db93a13ebde253f908b70871c46afc5ba" checksum = "a1100a056c5dcdd4e5513d5333385223b26ef1bf92f31eb38f407e8c20549256"
dependencies = [ dependencies = [
"libc", "libc",
] ]

View file

@ -37,7 +37,7 @@ rayon = { workspace = true, optional = true }
# Optional features. # Optional features.
heed = { version = "0.20.0-alpha.9", optional = true } heed = { version = "0.20.0-alpha.9", optional = true }
redb = { version = "1.5.0", optional = true } redb = { version = "2.0.0", optional = true }
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }
[dev-dependencies] [dev-dependencies]

View file

@ -77,7 +77,7 @@ where
} }
//---------------------------------------------------------------------------------------------------- DatabaseRo Impl //---------------------------------------------------------------------------------------------------- DatabaseRo Impl
impl<'tx, T: Table> DatabaseRo<'tx, T> for HeedTableRo<'tx, T> { impl<T: Table> DatabaseRo<T> for HeedTableRo<'_, T> {
#[inline] #[inline]
fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> { fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> {
get::<T>(&self.db, self.tx_ro, key) get::<T>(&self.db, self.tx_ro, key)
@ -96,7 +96,7 @@ impl<'tx, T: Table> DatabaseRo<'tx, T> for HeedTableRo<'tx, T> {
} }
//---------------------------------------------------------------------------------------------------- DatabaseRw Impl //---------------------------------------------------------------------------------------------------- DatabaseRw Impl
impl<'tx, T: Table> DatabaseRo<'tx, T> for HeedTableRw<'_, 'tx, T> { impl<T: Table> DatabaseRo<T> for HeedTableRw<'_, '_, T> {
#[inline] #[inline]
fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> { fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> {
get::<T>(&self.db, self.tx_rw, key) get::<T>(&self.db, self.tx_rw, key)
@ -114,7 +114,7 @@ impl<'tx, T: Table> DatabaseRo<'tx, T> for HeedTableRw<'_, 'tx, T> {
} }
} }
impl<'env, 'tx, T: Table> DatabaseRw<'env, 'tx, T> for HeedTableRw<'env, 'tx, T> { impl<T: Table> DatabaseRw<T> for HeedTableRw<'_, '_, T> {
#[inline] #[inline]
fn put(&mut self, key: &T::Key, value: &T::Value) -> Result<(), RuntimeError> { fn put(&mut self, key: &T::Key, value: &T::Value) -> Result<(), RuntimeError> {
Ok(self.db.put(self.tx_rw, key, value)?) Ok(self.db.put(self.tx_rw, key, value)?)

View file

@ -278,10 +278,10 @@ where
} }
#[inline] #[inline]
fn open_db_ro<'tx, T: Table>( fn open_db_ro<T: Table>(
&self, &self,
tx_ro: &'tx heed::RoTxn<'env>, tx_ro: &heed::RoTxn<'env>,
) -> Result<impl DatabaseRo<'tx, T>, RuntimeError> { ) -> Result<impl DatabaseRo<T>, RuntimeError> {
// Open up a read-only database using our table's const metadata. // Open up a read-only database using our table's const metadata.
Ok(HeedTableRo { Ok(HeedTableRo {
db: self db: self
@ -292,10 +292,10 @@ where
} }
#[inline] #[inline]
fn open_db_rw<'tx, T: Table>( fn open_db_rw<T: Table>(
&self, &self,
tx_rw: &'tx mut heed::RwTxn<'env>, tx_rw: &mut heed::RwTxn<'env>,
) -> Result<impl DatabaseRw<'env, 'tx, T>, RuntimeError> { ) -> Result<impl DatabaseRw<T>, RuntimeError> {
// Open up a read/write database using our table's const metadata. // Open up a read/write database using our table's const metadata.
Ok(HeedTableRw { Ok(HeedTableRw {
db: self db: self

View file

@ -49,7 +49,7 @@ where
} }
//---------------------------------------------------------------------------------------------------- DatabaseRo //---------------------------------------------------------------------------------------------------- DatabaseRo
impl<'tx, T: Table + 'static> DatabaseRo<'tx, T> for RedbTableRo<'tx, T::Key, T::Value> { impl<T: Table + 'static> DatabaseRo<T> for RedbTableRo<T::Key, T::Value> {
#[inline] #[inline]
fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> { fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> {
get::<T>(self, key) get::<T>(self, key)
@ -68,7 +68,7 @@ impl<'tx, T: Table + 'static> DatabaseRo<'tx, T> for RedbTableRo<'tx, T::Key, T:
} }
//---------------------------------------------------------------------------------------------------- DatabaseRw //---------------------------------------------------------------------------------------------------- DatabaseRw
impl<'tx, T: Table + 'static> DatabaseRo<'tx, T> for RedbTableRw<'_, 'tx, T::Key, T::Value> { impl<T: Table + 'static> DatabaseRo<T> for RedbTableRw<'_, T::Key, T::Value> {
#[inline] #[inline]
fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> { fn get(&self, key: &T::Key) -> Result<T::Value, RuntimeError> {
get::<T>(self, key) get::<T>(self, key)
@ -86,9 +86,7 @@ impl<'tx, T: Table + 'static> DatabaseRo<'tx, T> for RedbTableRw<'_, 'tx, T::Key
} }
} }
impl<'env, 'tx, T: Table + 'static> DatabaseRw<'env, 'tx, T> impl<T: Table + 'static> DatabaseRw<T> for RedbTableRw<'_, T::Key, T::Value> {
for RedbTableRw<'env, 'tx, T::Key, T::Value>
{
// `redb` returns the value after `insert()/remove()` // `redb` returns the value after `insert()/remove()`
// we end with Ok(()) instead. // we end with Ok(()) instead.

View file

@ -48,8 +48,8 @@ impl Env for ConcreteEnv {
const MANUAL_RESIZE: bool = false; const MANUAL_RESIZE: bool = false;
const SYNCS_PER_TX: bool = false; const SYNCS_PER_TX: bool = false;
type EnvInner<'env> = (&'env redb::Database, redb::Durability); type EnvInner<'env> = (&'env redb::Database, redb::Durability);
type TxRo<'tx> = redb::ReadTransaction<'tx>; type TxRo<'tx> = redb::ReadTransaction;
type TxRw<'tx> = redb::WriteTransaction<'tx>; type TxRw<'tx> = redb::WriteTransaction;
#[cold] #[cold]
#[inline(never)] // called once. #[inline(never)] // called once.
@ -88,7 +88,7 @@ impl Env for ConcreteEnv {
// <https://docs.rs/redb/latest/redb/struct.WriteTransaction.html#method.open_table> // <https://docs.rs/redb/latest/redb/struct.WriteTransaction.html#method.open_table>
/// Function that creates the tables based off the passed `T: Table`. /// Function that creates the tables based off the passed `T: Table`.
fn create_table<T: Table>(tx_rw: &redb::WriteTransaction<'_>) -> Result<(), InitError> { fn create_table<T: Table>(tx_rw: &redb::WriteTransaction) -> Result<(), InitError> {
println!("create_table(): {}", T::NAME); // TODO: use tracing. println!("create_table(): {}", T::NAME); // TODO: use tracing.
let table: redb::TableDefinition< let table: redb::TableDefinition<
@ -155,18 +155,18 @@ impl Env for ConcreteEnv {
} }
//---------------------------------------------------------------------------------------------------- EnvInner Impl //---------------------------------------------------------------------------------------------------- EnvInner Impl
impl<'env> EnvInner<'env, redb::ReadTransaction<'env>, redb::WriteTransaction<'env>> impl<'env> EnvInner<'env, redb::ReadTransaction, redb::WriteTransaction>
for (&'env redb::Database, redb::Durability) for (&'env redb::Database, redb::Durability)
where where
Self: 'env, Self: 'env,
{ {
#[inline] #[inline]
fn tx_ro(&'env self) -> Result<redb::ReadTransaction<'env>, RuntimeError> { fn tx_ro(&'env self) -> Result<redb::ReadTransaction, RuntimeError> {
Ok(self.0.begin_read()?) Ok(self.0.begin_read()?)
} }
#[inline] #[inline]
fn tx_rw(&'env self) -> Result<redb::WriteTransaction<'env>, RuntimeError> { fn tx_rw(&'env self) -> Result<redb::WriteTransaction, RuntimeError> {
// `redb` has sync modes on the TX level, unlike heed, // `redb` has sync modes on the TX level, unlike heed,
// which sets it at the Environment level. // which sets it at the Environment level.
// //
@ -177,10 +177,10 @@ where
} }
#[inline] #[inline]
fn open_db_ro<'tx, T: Table>( fn open_db_ro<T: Table>(
&self, &self,
tx_ro: &'tx redb::ReadTransaction<'env>, tx_ro: &redb::ReadTransaction,
) -> Result<impl DatabaseRo<'tx, T>, RuntimeError> { ) -> Result<impl DatabaseRo<T>, RuntimeError> {
// Open up a read-only database using our `T: Table`'s const metadata. // Open up a read-only database using our `T: Table`'s const metadata.
let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> = let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> =
redb::TableDefinition::new(T::NAME); redb::TableDefinition::new(T::NAME);
@ -190,10 +190,10 @@ where
} }
#[inline] #[inline]
fn open_db_rw<'tx, T: Table>( fn open_db_rw<T: Table>(
&self, &self,
tx_rw: &'tx mut redb::WriteTransaction<'env>, tx_rw: &mut redb::WriteTransaction,
) -> Result<impl DatabaseRw<'env, 'tx, T>, RuntimeError> { ) -> Result<impl DatabaseRw<T>, RuntimeError> {
// Open up a read/write database using our `T: Table`'s const metadata. // Open up a read/write database using our `T: Table`'s const metadata.
let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> = let table: redb::TableDefinition<'static, StorableRedb<T::Key>, StorableRedb<T::Value>> =
redb::TableDefinition::new(T::NAME); redb::TableDefinition::new(T::NAME);

View file

@ -3,7 +3,7 @@
//---------------------------------------------------------------------------------------------------- Use //---------------------------------------------------------------------------------------------------- Use
use std::{any::Any, borrow::Cow, cmp::Ordering, fmt::Debug, marker::PhantomData}; use std::{any::Any, borrow::Cow, cmp::Ordering, fmt::Debug, marker::PhantomData};
use redb::{RedbKey, RedbValue, TypeName}; use redb::TypeName;
use crate::{key::Key, storable::Storable}; use crate::{key::Key, storable::Storable};
@ -17,9 +17,9 @@ pub(super) struct StorableRedb<T>(PhantomData<T>)
where where
T: Storable; T: Storable;
//---------------------------------------------------------------------------------------------------- RedbKey //---------------------------------------------------------------------------------------------------- redb::Key
// If `Key` is also implemented, this can act as a `RedbKey`. // If `Key` is also implemented, this can act as a `redb::Key`.
impl<T> RedbKey for StorableRedb<T> impl<T> redb::Key for StorableRedb<T>
where where
T: Key + 'static, T: Key + 'static,
{ {
@ -29,8 +29,8 @@ where
} }
} }
//---------------------------------------------------------------------------------------------------- RedbValue //---------------------------------------------------------------------------------------------------- redb::Value
impl<T> RedbValue for StorableRedb<T> impl<T> redb::Value for StorableRedb<T>
where where
T: Storable + 'static, T: Storable + 'static,
{ {
@ -77,7 +77,7 @@ mod test {
// - make sure the right function is being called // - make sure the right function is being called
#[test] #[test]
/// Assert `RedbKey::compare` works for `StorableRedb`. /// Assert `redb::Key::compare` works for `StorableRedb`.
fn compare() { fn compare() {
fn test<T>(left: T, right: T, expected: Ordering) fn test<T>(left: T, right: T, expected: Ordering)
where where
@ -85,9 +85,9 @@ mod test {
{ {
println!("left: {left:?}, right: {right:?}, expected: {expected:?}"); println!("left: {left:?}, right: {right:?}, expected: {expected:?}");
assert_eq!( assert_eq!(
<StorableRedb::<T> as RedbKey>::compare( <StorableRedb::<T> as redb::Key>::compare(
<StorableRedb::<T> as RedbValue>::as_bytes(&left), <StorableRedb::<T> as redb::Value>::as_bytes(&left),
<StorableRedb::<T> as RedbValue>::as_bytes(&right) <StorableRedb::<T> as redb::Value>::as_bytes(&right)
), ),
expected expected
); );
@ -100,13 +100,13 @@ mod test {
} }
#[test] #[test]
/// Assert `RedbKey::fixed_width` is accurate. /// Assert `redb::Key::fixed_width` is accurate.
fn fixed_width() { fn fixed_width() {
fn test<T>(expected: Option<usize>) fn test<T>(expected: Option<usize>)
where where
T: Storable + 'static, T: Storable + 'static,
{ {
assert_eq!(<StorableRedb::<T> as RedbValue>::fixed_width(), expected); assert_eq!(<StorableRedb::<T> as redb::Value>::fixed_width(), expected);
} }
test::<()>(Some(0)); test::<()>(Some(0));
@ -127,14 +127,14 @@ mod test {
} }
#[test] #[test]
/// Assert `RedbKey::as_bytes` is accurate. /// Assert `redb::Key::as_bytes` is accurate.
fn as_bytes() { fn as_bytes() {
fn test<T>(t: &T, expected: &[u8]) fn test<T>(t: &T, expected: &[u8])
where where
T: Storable + 'static, T: Storable + 'static,
{ {
println!("t: {t:?}, expected: {expected:?}"); println!("t: {t:?}, expected: {expected:?}");
assert_eq!(<StorableRedb::<T> as RedbValue>::as_bytes(t), expected); assert_eq!(<StorableRedb::<T> as redb::Value>::as_bytes(t), expected);
} }
test::<()>(&(), &[]); test::<()>(&(), &[]);
@ -155,7 +155,7 @@ mod test {
} }
#[test] #[test]
/// Assert `RedbKey::from_bytes` is accurate. /// Assert `redb::Key::from_bytes` is accurate.
fn from_bytes() { fn from_bytes() {
fn test<T>(bytes: &[u8], expected: &T) fn test<T>(bytes: &[u8], expected: &T)
where where
@ -163,7 +163,7 @@ mod test {
{ {
println!("bytes: {bytes:?}, expected: {expected:?}"); println!("bytes: {bytes:?}, expected: {expected:?}");
assert_eq!( assert_eq!(
&<StorableRedb::<T> as RedbValue>::from_bytes(bytes), &<StorableRedb::<T> as redb::Value>::from_bytes(bytes),
expected expected
); );
} }
@ -186,27 +186,27 @@ mod test {
} }
#[test] #[test]
/// Assert `RedbKey::type_name` returns unique names. /// Assert `redb::Key::type_name` returns unique names.
/// The name itself isn't tested, the invariant is that /// The name itself isn't tested, the invariant is that
/// they are all unique. /// they are all unique.
fn type_name() { fn type_name() {
// Can't use a proper set because `redb::TypeName: !Ord`. // Can't use a proper set because `redb::TypeName: !Ord`.
let set = [ let set = [
<StorableRedb<()> as RedbValue>::type_name(), <StorableRedb<()> as redb::Value>::type_name(),
<StorableRedb<u8> as RedbValue>::type_name(), <StorableRedb<u8> as redb::Value>::type_name(),
<StorableRedb<u16> as RedbValue>::type_name(), <StorableRedb<u16> as redb::Value>::type_name(),
<StorableRedb<u32> as RedbValue>::type_name(), <StorableRedb<u32> as redb::Value>::type_name(),
<StorableRedb<u64> as RedbValue>::type_name(), <StorableRedb<u64> as redb::Value>::type_name(),
<StorableRedb<i8> as RedbValue>::type_name(), <StorableRedb<i8> as redb::Value>::type_name(),
<StorableRedb<i16> as RedbValue>::type_name(), <StorableRedb<i16> as redb::Value>::type_name(),
<StorableRedb<i32> as RedbValue>::type_name(), <StorableRedb<i32> as redb::Value>::type_name(),
<StorableRedb<i64> as RedbValue>::type_name(), <StorableRedb<i64> as redb::Value>::type_name(),
<StorableRedb<StorableVec<u8>> as RedbValue>::type_name(), <StorableRedb<StorableVec<u8>> as redb::Value>::type_name(),
<StorableRedb<StorableBytes> as RedbValue>::type_name(), <StorableRedb<StorableBytes> as redb::Value>::type_name(),
<StorableRedb<[u8; 0]> as RedbValue>::type_name(), <StorableRedb<[u8; 0]> as redb::Value>::type_name(),
<StorableRedb<[u8; 1]> as RedbValue>::type_name(), <StorableRedb<[u8; 1]> as redb::Value>::type_name(),
<StorableRedb<[u8; 2]> as RedbValue>::type_name(), <StorableRedb<[u8; 2]> as redb::Value>::type_name(),
<StorableRedb<[u8; 3]> as RedbValue>::type_name(), <StorableRedb<[u8; 3]> as redb::Value>::type_name(),
]; ];
// Check every permutation is unique. // Check every permutation is unique.

View file

@ -9,17 +9,21 @@ use crate::{
}; };
//---------------------------------------------------------------------------------------------------- TxRo //---------------------------------------------------------------------------------------------------- TxRo
impl TxRo<'_> for redb::ReadTransaction<'_> { impl TxRo<'_> for redb::ReadTransaction {
/// This function is infallible. /// This function is infallible.
fn commit(self) -> Result<(), RuntimeError> { fn commit(self) -> Result<(), RuntimeError> {
// `redb`'s read transactions cleanup in their `drop()`, there is no `commit()`. // `redb`'s read transactions cleanup automatically when all references are dropped.
// https://docs.rs/redb/latest/src/redb/transactions.rs.html#1258-1265 //
// There is `close()`:
// <https://docs.rs/redb/2.0.0/redb/struct.ReadTransaction.html#method.close>
// but this will error if there are outstanding references, i.e. an open table.
// This is unwanted behavior in our case, so we don't call this.
Ok(()) Ok(())
} }
} }
//---------------------------------------------------------------------------------------------------- TxRw //---------------------------------------------------------------------------------------------------- TxRw
impl TxRw<'_> for redb::WriteTransaction<'_> { impl TxRw<'_> for redb::WriteTransaction {
fn commit(self) -> Result<(), RuntimeError> { fn commit(self) -> Result<(), RuntimeError> {
Ok(self.commit()?) Ok(self.commit()?)
} }

View file

@ -5,9 +5,7 @@ use crate::{backend::redb::storable::StorableRedb, table::Table};
//---------------------------------------------------------------------------------------------------- Types //---------------------------------------------------------------------------------------------------- Types
/// The concrete type for readable `redb` tables. /// The concrete type for readable `redb` tables.
pub(super) type RedbTableRo<'env, K, V> = pub(super) type RedbTableRo<K, V> = redb::ReadOnlyTable<StorableRedb<K>, StorableRedb<V>>;
redb::ReadOnlyTable<'env, StorableRedb<K>, StorableRedb<V>>;
/// The concrete type for readable/writable `redb` tables. /// The concrete type for readable/writable `redb` tables.
pub(super) type RedbTableRw<'env, 'tx, K, V> = pub(super) type RedbTableRw<'tx, K, V> = redb::Table<'tx, StorableRedb<K>, StorableRedb<V>>;
redb::Table<'env, 'tx, StorableRedb<K>, StorableRedb<V>>;

View file

@ -18,7 +18,7 @@ use crate::{
/// ///
/// This is a read-only database table, /// This is a read-only database table,
/// write operations are defined in [`DatabaseRw`]. /// write operations are defined in [`DatabaseRw`].
pub trait DatabaseRo<'tx, T: Table> { pub trait DatabaseRo<T: Table> {
/// Get the value corresponding to a key. /// Get the value corresponding to a key.
/// ///
/// The returned value is _owned_. /// The returned value is _owned_.
@ -51,7 +51,7 @@ pub trait DatabaseRo<'tx, T: Table> {
/// Database (key-value store) read/write abstraction. /// Database (key-value store) read/write abstraction.
/// ///
/// All [`DatabaseRo`] functions are also callable by [`DatabaseRw`]. /// All [`DatabaseRo`] functions are also callable by [`DatabaseRw`].
pub trait DatabaseRw<'env, 'tx, T: Table>: DatabaseRo<'tx, T> { pub trait DatabaseRw<T: Table>: DatabaseRo<T> {
/// Insert a key-value pair into the database. /// Insert a key-value pair into the database.
/// ///
/// This will overwrite any existing key-value pairs. /// This will overwrite any existing key-value pairs.

View file

@ -199,10 +199,7 @@ where
/// As [`Table`] is `Sealed`, and all tables are created /// As [`Table`] is `Sealed`, and all tables are created
/// upon [`Env::open`], this function will never error because /// upon [`Env::open`], this function will never error because
/// a table doesn't exist. /// a table doesn't exist.
fn open_db_ro<'tx, T: Table>( fn open_db_ro<T: Table>(&self, tx_ro: &Ro) -> Result<impl DatabaseRo<T>, RuntimeError>;
&self,
tx_ro: &'tx Ro,
) -> Result<impl DatabaseRo<'tx, T>, RuntimeError>;
/// Open a database in read/write mode. /// Open a database in read/write mode.
/// ///
@ -216,8 +213,5 @@ where
/// As [`Table`] is `Sealed`, and all tables are created /// As [`Table`] is `Sealed`, and all tables are created
/// upon [`Env::open`], this function will never error because /// upon [`Env::open`], this function will never error because
/// a table doesn't exist. /// a table doesn't exist.
fn open_db_rw<'tx, T: Table>( fn open_db_rw<T: Table>(&self, tx_rw: &mut Rw) -> Result<impl DatabaseRw<T>, RuntimeError>;
&self,
tx_rw: &'tx mut Rw,
) -> Result<impl DatabaseRw<'env, 'tx, T>, RuntimeError>;
} }