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]]
name = "redb"
version = "1.5.0"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72623e6275cd430215b741f41ebda34db93a13ebde253f908b70871c46afc5ba"
checksum = "a1100a056c5dcdd4e5513d5333385223b26ef1bf92f31eb38f407e8c20549256"
dependencies = [
"libc",
]

View file

@ -37,7 +37,7 @@ rayon = { workspace = true, optional = true }
# Optional features.
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 }
[dev-dependencies]

View file

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

View file

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

View file

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

View file

@ -48,8 +48,8 @@ impl Env for ConcreteEnv {
const MANUAL_RESIZE: bool = false;
const SYNCS_PER_TX: bool = false;
type EnvInner<'env> = (&'env redb::Database, redb::Durability);
type TxRo<'tx> = redb::ReadTransaction<'tx>;
type TxRw<'tx> = redb::WriteTransaction<'tx>;
type TxRo<'tx> = redb::ReadTransaction;
type TxRw<'tx> = redb::WriteTransaction;
#[cold]
#[inline(never)] // called once.
@ -88,7 +88,7 @@ impl Env for ConcreteEnv {
// <https://docs.rs/redb/latest/redb/struct.WriteTransaction.html#method.open_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.
let table: redb::TableDefinition<
@ -155,18 +155,18 @@ impl Env for ConcreteEnv {
}
//---------------------------------------------------------------------------------------------------- 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)
where
Self: 'env,
{
#[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()?)
}
#[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,
// which sets it at the Environment level.
//
@ -177,10 +177,10 @@ where
}
#[inline]
fn open_db_ro<'tx, T: Table>(
fn open_db_ro<T: Table>(
&self,
tx_ro: &'tx redb::ReadTransaction<'env>,
) -> Result<impl DatabaseRo<'tx, T>, RuntimeError> {
tx_ro: &redb::ReadTransaction,
) -> Result<impl DatabaseRo<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>> =
redb::TableDefinition::new(T::NAME);
@ -190,10 +190,10 @@ where
}
#[inline]
fn open_db_rw<'tx, T: Table>(
fn open_db_rw<T: Table>(
&self,
tx_rw: &'tx mut redb::WriteTransaction<'env>,
) -> Result<impl DatabaseRw<'env, 'tx, T>, RuntimeError> {
tx_rw: &mut redb::WriteTransaction,
) -> 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>> =
redb::TableDefinition::new(T::NAME);

View file

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

View file

@ -9,17 +9,21 @@ use crate::{
};
//---------------------------------------------------------------------------------------------------- TxRo
impl TxRo<'_> for redb::ReadTransaction<'_> {
impl TxRo<'_> for redb::ReadTransaction {
/// This function is infallible.
fn commit(self) -> Result<(), RuntimeError> {
// `redb`'s read transactions cleanup in their `drop()`, there is no `commit()`.
// https://docs.rs/redb/latest/src/redb/transactions.rs.html#1258-1265
// `redb`'s read transactions cleanup automatically when all references are dropped.
//
// 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(())
}
}
//---------------------------------------------------------------------------------------------------- TxRw
impl TxRw<'_> for redb::WriteTransaction<'_> {
impl TxRw<'_> for redb::WriteTransaction {
fn commit(self) -> Result<(), RuntimeError> {
Ok(self.commit()?)
}

View file

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

View file

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

View file

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