mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-11-16 15:58:17 +00:00
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:
parent
3656a1ada7
commit
5e7ee57482
11 changed files with 73 additions and 79 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)?)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()?)
|
||||
}
|
||||
|
|
|
@ -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>>;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue