feat: get rid of cursor lifetime (#5476)

This commit is contained in:
Matthias Seitz
2023-11-17 21:37:34 +01:00
committed by GitHub
parent 9b1416b4f4
commit 7f9ce6f7c0
10 changed files with 194 additions and 213 deletions

10
Cargo.lock generated
View File

@ -4007,15 +4007,6 @@ dependencies = [
"redox_syscall 0.4.1", "redox_syscall 0.4.1",
] ]
[[package]]
name = "lifetimed-bytes"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c970c8ea4c7b023a41cfa4af4c785a16694604c2f2a3b0d1f20a9bcb73fa550"
dependencies = [
"bytes",
]
[[package]] [[package]]
name = "linked-hash-map" name = "linked-hash-map"
version = "0.5.6" version = "0.5.6"
@ -6027,7 +6018,6 @@ dependencies = [
"derive_more", "derive_more",
"indexmap 2.1.0", "indexmap 2.1.0",
"libc", "libc",
"lifetimed-bytes",
"parking_lot 0.12.1", "parking_lot 0.12.1",
"pprof", "pprof",
"rand 0.8.5", "rand 0.8.5",

View File

@ -166,7 +166,7 @@ mod tests {
assert!(acc_indexing_stage.execute(&provider, input).await.is_err()); assert!(acc_indexing_stage.execute(&provider, input).await.is_err());
} else { } else {
acc_indexing_stage.execute(&provider, input).await.unwrap(); acc_indexing_stage.execute(&provider, input).await.unwrap();
let mut account_history: Cursor<'_, RW, AccountHistory> = let mut account_history: Cursor<RW, AccountHistory> =
provider.tx_ref().cursor_read::<tables::AccountHistory>().unwrap(); provider.tx_ref().cursor_read::<tables::AccountHistory>().unwrap();
assert_eq!(account_history.walk(None).unwrap().count(), expect_num_acc_changesets); assert_eq!(account_history.walk(None).unwrap().count(), expect_num_acc_changesets);
} }

View File

@ -17,15 +17,15 @@ use crate::{
use reth_libmdbx::{self, Error as MDBXError, TransactionKind, WriteFlags, RO, RW}; use reth_libmdbx::{self, Error as MDBXError, TransactionKind, WriteFlags, RO, RW};
/// Read only Cursor. /// Read only Cursor.
pub type CursorRO<'tx, T> = Cursor<'tx, RO, T>; pub type CursorRO<T> = Cursor<RO, T>;
/// Read write cursor. /// Read write cursor.
pub type CursorRW<'tx, T> = Cursor<'tx, RW, T>; pub type CursorRW<T> = Cursor<RW, T>;
/// Cursor wrapper to access KV items. /// Cursor wrapper to access KV items.
#[derive(Debug)] #[derive(Debug)]
pub struct Cursor<'tx, K: TransactionKind, T: Table> { pub struct Cursor<K: TransactionKind, T: Table> {
/// Inner `libmdbx` cursor. /// Inner `libmdbx` cursor.
pub(crate) inner: reth_libmdbx::Cursor<'tx, K>, pub(crate) inner: reth_libmdbx::Cursor<K>,
/// Cache buffer that receives compressed values. /// Cache buffer that receives compressed values.
buf: Vec<u8>, buf: Vec<u8>,
/// Whether to record metrics or not. /// Whether to record metrics or not.
@ -34,11 +34,8 @@ pub struct Cursor<'tx, K: TransactionKind, T: Table> {
_dbi: PhantomData<T>, _dbi: PhantomData<T>,
} }
impl<'tx, K: TransactionKind, T: Table> Cursor<'tx, K, T> { impl<K: TransactionKind, T: Table> Cursor<K, T> {
pub(crate) fn new_with_metrics( pub(crate) fn new_with_metrics(inner: reth_libmdbx::Cursor<K>, with_metrics: bool) -> Self {
inner: reth_libmdbx::Cursor<'tx, K>,
with_metrics: bool,
) -> Self {
Self { inner, buf: Vec::new(), with_metrics, _dbi: PhantomData } Self { inner, buf: Vec::new(), with_metrics, _dbi: PhantomData }
} }
@ -81,7 +78,7 @@ macro_rules! compress_to_buf_or_ref {
}; };
} }
impl<K: TransactionKind, T: Table> DbCursorRO<T> for Cursor<'_, K, T> { impl<K: TransactionKind, T: Table> DbCursorRO<T> for Cursor<K, T> {
fn first(&mut self) -> PairResult<T> { fn first(&mut self) -> PairResult<T> {
decode!(self.inner.first()) decode!(self.inner.first())
} }
@ -164,7 +161,7 @@ impl<K: TransactionKind, T: Table> DbCursorRO<T> for Cursor<'_, K, T> {
} }
} }
impl<K: TransactionKind, T: DupSort> DbDupCursorRO<T> for Cursor<'_, K, T> { impl<K: TransactionKind, T: DupSort> DbDupCursorRO<T> for Cursor<K, T> {
/// Returns the next `(key, value)` pair of a DUPSORT table. /// Returns the next `(key, value)` pair of a DUPSORT table.
fn next_dup(&mut self) -> PairResult<T> { fn next_dup(&mut self) -> PairResult<T> {
decode!(self.inner.next_dup()) decode!(self.inner.next_dup())
@ -245,7 +242,7 @@ impl<K: TransactionKind, T: DupSort> DbDupCursorRO<T> for Cursor<'_, K, T> {
} }
} }
impl<T: Table> DbCursorRW<T> for Cursor<'_, RW, T> { impl<T: Table> DbCursorRW<T> for Cursor<RW, T> {
/// Database operation that will update an existing row if a specified value already /// Database operation that will update an existing row if a specified value already
/// exists in a table, and insert a new row if the specified value doesn't already exist /// exists in a table, and insert a new row if the specified value doesn't already exist
/// ///
@ -328,7 +325,7 @@ impl<T: Table> DbCursorRW<T> for Cursor<'_, RW, T> {
} }
} }
impl<T: DupSort> DbDupCursorRW<T> for Cursor<'_, RW, T> { impl<T: DupSort> DbDupCursorRW<T> for Cursor<RW, T> {
fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> { fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> {
self.execute_with_operation_metric(Operation::CursorDeleteCurrentDuplicates, None, |this| { self.execute_with_operation_metric(Operation::CursorDeleteCurrentDuplicates, None, |this| {
this.inner.del(WriteFlags::NO_DUP_DATA).map_err(|e| DatabaseError::Delete(e.into())) this.inner.del(WriteFlags::NO_DUP_DATA).map_err(|e| DatabaseError::Delete(e.into()))

View File

@ -75,7 +75,7 @@ impl<K: TransactionKind> Tx<K> {
} }
/// Create db Cursor /// Create db Cursor
pub fn new_cursor<T: Table>(&self) -> Result<Cursor<'_, K, T>, DatabaseError> { pub fn new_cursor<T: Table>(&self) -> Result<Cursor<K, T>, DatabaseError> {
let inner = self let inner = self
.inner .inner
.cursor_with_dbi(self.get_dbi::<T>()?) .cursor_with_dbi(self.get_dbi::<T>()?)
@ -168,13 +168,13 @@ impl<K: TransactionKind> Drop for MetricsHandler<K> {
} }
impl<'a, K: TransactionKind> DbTxGAT<'a> for Tx<K> { impl<'a, K: TransactionKind> DbTxGAT<'a> for Tx<K> {
type Cursor<T: Table> = Cursor<'a, K, T>; type Cursor<T: Table> = Cursor<K, T>;
type DupCursor<T: DupSort> = Cursor<'a, K, T>; type DupCursor<T: DupSort> = Cursor<K, T>;
} }
impl<'a, K: TransactionKind> DbTxMutGAT<'a> for Tx<K> { impl<'a, K: TransactionKind> DbTxMutGAT<'a> for Tx<K> {
type CursorMut<T: Table> = Cursor<'a, RW, T>; type CursorMut<T: Table> = Cursor<RW, T>;
type DupCursorMut<T: DupSort> = Cursor<'a, RW, T>; type DupCursorMut<T: DupSort> = Cursor<RW, T>;
} }
impl TableImporter for Tx<RW> {} impl TableImporter for Tx<RW> {}

View File

@ -22,8 +22,6 @@ thiserror.workspace = true
ffi = { package = "reth-mdbx-sys", path = "./mdbx-sys" } ffi = { package = "reth-mdbx-sys", path = "./mdbx-sys" }
lifetimed-bytes = { version = "0.1", optional = true }
[features] [features]
default = [] default = []
return-borrowed = [] return-borrowed = []

View File

@ -33,7 +33,7 @@ fn bench_get_seq_iter(c: &mut Criterion) {
count += 1; count += 1;
} }
fn iterate<K: TransactionKind>(cursor: &mut Cursor<'_, K>) -> Result<()> { fn iterate<K: TransactionKind>(cursor: &mut Cursor<K>) -> Result<()> {
let mut i = 0; let mut i = 0;
for result in cursor.iter::<ObjectLength, ObjectLength>() { for result in cursor.iter::<ObjectLength, ObjectLength>() {
let (key_len, data_len) = result?; let (key_len, data_len) = result?;

View File

@ -3,7 +3,7 @@ use derive_more::*;
use std::{borrow::Cow, slice}; use std::{borrow::Cow, slice};
/// Implement this to be able to decode data values /// Implement this to be able to decode data values
pub trait TableObject<'tx> { pub trait TableObject {
/// Decodes the object from the given bytes. /// Decodes the object from the given bytes.
fn decode(data_val: &[u8]) -> Result<Self, Error> fn decode(data_val: &[u8]) -> Result<Self, Error>
where where
@ -28,7 +28,7 @@ pub trait TableObject<'tx> {
} }
} }
impl<'tx> TableObject<'tx> for Cow<'tx, [u8]> { impl<'tx> TableObject for Cow<'tx, [u8]> {
fn decode(_: &[u8]) -> Result<Self, Error> { fn decode(_: &[u8]) -> Result<Self, Error> {
unreachable!() unreachable!()
} }
@ -55,22 +55,7 @@ impl<'tx> TableObject<'tx> for Cow<'tx, [u8]> {
} }
} }
#[cfg(feature = "lifetimed-bytes")] impl TableObject for Vec<u8> {
impl<'tx> TableObject<'tx> for lifetimed_bytes::Bytes<'tx> {
fn decode(_: &[u8]) -> Result<Self, Error> {
unreachable!()
}
#[doc(hidden)]
unsafe fn decode_val<K: TransactionKind>(
txn: *const ffi::MDBX_txn,
data_val: &ffi::MDBX_val,
) -> Result<Self, Error> {
Cow::<'tx, [u8]>::decode_val::<K>(txn, data_val).map(From::from)
}
}
impl<'tx> TableObject<'tx> for Vec<u8> {
fn decode(data_val: &[u8]) -> Result<Self, Error> fn decode(data_val: &[u8]) -> Result<Self, Error>
where where
Self: Sized, Self: Sized,
@ -79,7 +64,7 @@ impl<'tx> TableObject<'tx> for Vec<u8> {
} }
} }
impl<'tx> TableObject<'tx> for () { impl TableObject for () {
fn decode(_: &[u8]) -> Result<Self, Error> { fn decode(_: &[u8]) -> Result<Self, Error> {
Ok(()) Ok(())
} }
@ -96,7 +81,7 @@ impl<'tx> TableObject<'tx> for () {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deref, DerefMut)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deref, DerefMut)]
pub struct ObjectLength(pub usize); pub struct ObjectLength(pub usize);
impl<'tx> TableObject<'tx> for ObjectLength { impl TableObject for ObjectLength {
fn decode(data_val: &[u8]) -> Result<Self, Error> fn decode(data_val: &[u8]) -> Result<Self, Error>
where where
Self: Sized, Self: Sized,
@ -105,7 +90,7 @@ impl<'tx> TableObject<'tx> for ObjectLength {
} }
} }
impl<'tx, const LEN: usize> TableObject<'tx> for [u8; LEN] { impl<const LEN: usize> TableObject for [u8; LEN] {
fn decode(data_val: &[u8]) -> Result<Self, Error> fn decode(data_val: &[u8]) -> Result<Self, Error>
where where
Self: Sized, Self: Sized,

View File

@ -1,40 +1,41 @@
use crate::{ use std::{borrow::Cow, fmt, marker::PhantomData, mem, ptr};
error::{mdbx_result, Error, Result},
flags::*, use libc::c_void;
mdbx_try_optional,
transaction::{TransactionKind, TransactionPtr, RW},
TableObject, Transaction,
};
use ffi::{ use ffi::{
MDBX_cursor_op, MDBX_FIRST, MDBX_FIRST_DUP, MDBX_GET_BOTH, MDBX_GET_BOTH_RANGE, MDBX_cursor_op, MDBX_FIRST, MDBX_FIRST_DUP, MDBX_GET_BOTH, MDBX_GET_BOTH_RANGE,
MDBX_GET_CURRENT, MDBX_GET_MULTIPLE, MDBX_LAST, MDBX_LAST_DUP, MDBX_NEXT, MDBX_NEXT_DUP, MDBX_GET_CURRENT, MDBX_GET_MULTIPLE, MDBX_LAST, MDBX_LAST_DUP, MDBX_NEXT, MDBX_NEXT_DUP,
MDBX_NEXT_MULTIPLE, MDBX_NEXT_NODUP, MDBX_PREV, MDBX_PREV_DUP, MDBX_PREV_MULTIPLE, MDBX_NEXT_MULTIPLE, MDBX_NEXT_NODUP, MDBX_PREV, MDBX_PREV_DUP, MDBX_PREV_MULTIPLE,
MDBX_PREV_NODUP, MDBX_SET, MDBX_SET_KEY, MDBX_SET_LOWERBOUND, MDBX_SET_RANGE, MDBX_PREV_NODUP, MDBX_SET, MDBX_SET_KEY, MDBX_SET_LOWERBOUND, MDBX_SET_RANGE,
}; };
use libc::c_void;
use std::{borrow::Cow, fmt, marker::PhantomData, mem, ptr}; use crate::{
error::{mdbx_result, Error, Result},
flags::*,
mdbx_try_optional,
transaction::{TransactionKind, RW},
TableObject, Transaction,
};
/// A cursor for navigating the items within a database. /// A cursor for navigating the items within a database.
pub struct Cursor<'txn, K> pub struct Cursor<K>
where where
K: TransactionKind, K: TransactionKind,
{ {
txn: TransactionPtr, txn: Transaction<K>,
cursor: *mut ffi::MDBX_cursor, cursor: *mut ffi::MDBX_cursor,
_marker: PhantomData<fn(&'txn (), K)>,
} }
impl<'txn, K> Cursor<'txn, K> impl<K> Cursor<K>
where where
K: TransactionKind, K: TransactionKind,
{ {
pub(crate) fn new(txn: &'txn Transaction<K>, dbi: ffi::MDBX_dbi) -> Result<Self> { pub(crate) fn new(txn: Transaction<K>, dbi: ffi::MDBX_dbi) -> Result<Self> {
let mut cursor: *mut ffi::MDBX_cursor = ptr::null_mut(); let mut cursor: *mut ffi::MDBX_cursor = ptr::null_mut();
let txn = txn.txn_ptr();
unsafe { unsafe {
mdbx_result(txn.txn_execute(|txn| ffi::mdbx_cursor_open(txn, dbi, &mut cursor)))?; mdbx_result(txn.txn_execute(|txn| ffi::mdbx_cursor_open(txn, dbi, &mut cursor)))?;
} }
Ok(Self { txn, cursor, _marker: PhantomData }) Ok(Self { txn, cursor })
} }
fn new_at_position(other: &Self) -> Result<Self> { fn new_at_position(other: &Self) -> Result<Self> {
@ -43,7 +44,7 @@ where
let res = ffi::mdbx_cursor_copy(other.cursor(), cursor); let res = ffi::mdbx_cursor_copy(other.cursor(), cursor);
let s = Self { txn: other.txn.clone(), cursor, _marker: PhantomData }; let s = Self { txn: other.txn.clone(), cursor };
mdbx_result(res)?; mdbx_result(res)?;
@ -59,6 +60,24 @@ where
self.cursor self.cursor
} }
/// Returns an Iterator over the raw key value slices
///
/// Note: The lifetime ensures that the transaction is kept alive while entries are used
pub fn into_iter_slices<'cur>(self) -> IntoIter<'cur, K, Cow<'cur, [u8]>, Cow<'cur, [u8]>> {
self.into_iter()
}
/// Returns an Iterator over key value pairs of the cursor
///
/// Note: The lifetime ensures that the transaction is kept alive while entries are used
#[allow(clippy::should_implement_trait)]
pub fn into_iter<'cur, Key, Value>(self) -> IntoIter<'cur, K, Key, Value>
where
Key: TableObject,
Value: TableObject,
{
IntoIter::new(self, MDBX_NEXT, MDBX_NEXT)
}
/// Retrieves a key/data pair from the cursor. Depending on the cursor op, /// Retrieves a key/data pair from the cursor. Depending on the cursor op,
/// the current key may be returned. /// the current key may be returned.
fn get<Key, Value>( fn get<Key, Value>(
@ -68,8 +87,8 @@ where
op: MDBX_cursor_op, op: MDBX_cursor_op,
) -> Result<(Option<Key>, Value, bool)> ) -> Result<(Option<Key>, Value, bool)>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
unsafe { unsafe {
let mut key_val = slice_to_val(key); let mut key_val = slice_to_val(key);
@ -105,7 +124,7 @@ where
op: MDBX_cursor_op, op: MDBX_cursor_op,
) -> Result<Option<Value>> ) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
let (_, v, _) = mdbx_try_optional!(self.get::<(), Value>(key, data, op)); let (_, v, _) = mdbx_try_optional!(self.get::<(), Value>(key, data, op));
@ -119,8 +138,8 @@ where
op: MDBX_cursor_op, op: MDBX_cursor_op,
) -> Result<Option<(Key, Value)>> ) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
let (k, v, _) = mdbx_try_optional!(self.get(key, data, op)); let (k, v, _) = mdbx_try_optional!(self.get(key, data, op));
@ -130,8 +149,8 @@ where
/// Position at first key/data item. /// Position at first key/data item.
pub fn first<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn first<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_FIRST) self.get_full(None, None, MDBX_FIRST)
} }
@ -139,7 +158,7 @@ where
/// [DatabaseFlags::DUP_SORT]-only: Position at first data item of current key. /// [DatabaseFlags::DUP_SORT]-only: Position at first data item of current key.
pub fn first_dup<Value>(&mut self) -> Result<Option<Value>> pub fn first_dup<Value>(&mut self) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(None, None, MDBX_FIRST_DUP) self.get_value(None, None, MDBX_FIRST_DUP)
} }
@ -147,7 +166,7 @@ where
/// [DatabaseFlags::DUP_SORT]-only: Position at key/data pair. /// [DatabaseFlags::DUP_SORT]-only: Position at key/data pair.
pub fn get_both<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>> pub fn get_both<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(Some(k), Some(v), MDBX_GET_BOTH) self.get_value(Some(k), Some(v), MDBX_GET_BOTH)
} }
@ -156,7 +175,7 @@ where
/// equal to specified data. /// equal to specified data.
pub fn get_both_range<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>> pub fn get_both_range<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(Some(k), Some(v), MDBX_GET_BOTH_RANGE) self.get_value(Some(k), Some(v), MDBX_GET_BOTH_RANGE)
} }
@ -164,8 +183,8 @@ where
/// Return key/data at current cursor position. /// Return key/data at current cursor position.
pub fn get_current<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn get_current<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_GET_CURRENT) self.get_full(None, None, MDBX_GET_CURRENT)
} }
@ -174,7 +193,7 @@ where
/// Move cursor to prepare for [Self::next_multiple()]. /// Move cursor to prepare for [Self::next_multiple()].
pub fn get_multiple<Value>(&mut self) -> Result<Option<Value>> pub fn get_multiple<Value>(&mut self) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(None, None, MDBX_GET_MULTIPLE) self.get_value(None, None, MDBX_GET_MULTIPLE)
} }
@ -182,8 +201,8 @@ where
/// Position at last key/data item. /// Position at last key/data item.
pub fn last<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn last<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_LAST) self.get_full(None, None, MDBX_LAST)
} }
@ -191,7 +210,7 @@ where
/// DupSort-only: Position at last data item of current key. /// DupSort-only: Position at last data item of current key.
pub fn last_dup<Value>(&mut self) -> Result<Option<Value>> pub fn last_dup<Value>(&mut self) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(None, None, MDBX_LAST_DUP) self.get_value(None, None, MDBX_LAST_DUP)
} }
@ -200,8 +219,8 @@ where
#[allow(clippy::should_implement_trait)] #[allow(clippy::should_implement_trait)]
pub fn next<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn next<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_NEXT) self.get_full(None, None, MDBX_NEXT)
} }
@ -209,8 +228,8 @@ where
/// [DatabaseFlags::DUP_SORT]-only: Position at next data item of current key. /// [DatabaseFlags::DUP_SORT]-only: Position at next data item of current key.
pub fn next_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn next_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_NEXT_DUP) self.get_full(None, None, MDBX_NEXT_DUP)
} }
@ -219,8 +238,8 @@ where
/// cursor position. Move cursor to prepare for MDBX_NEXT_MULTIPLE. /// cursor position. Move cursor to prepare for MDBX_NEXT_MULTIPLE.
pub fn next_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn next_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_NEXT_MULTIPLE) self.get_full(None, None, MDBX_NEXT_MULTIPLE)
} }
@ -228,8 +247,8 @@ where
/// Position at first data item of next key. /// Position at first data item of next key.
pub fn next_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn next_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_NEXT_NODUP) self.get_full(None, None, MDBX_NEXT_NODUP)
} }
@ -237,8 +256,8 @@ where
/// Position at previous data item. /// Position at previous data item.
pub fn prev<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn prev<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_PREV) self.get_full(None, None, MDBX_PREV)
} }
@ -246,8 +265,8 @@ where
/// [DatabaseFlags::DUP_SORT]-only: Position at previous data item of current key. /// [DatabaseFlags::DUP_SORT]-only: Position at previous data item of current key.
pub fn prev_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn prev_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_PREV_DUP) self.get_full(None, None, MDBX_PREV_DUP)
} }
@ -255,8 +274,8 @@ where
/// Position at last data item of previous key. /// Position at last data item of previous key.
pub fn prev_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn prev_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_PREV_NODUP) self.get_full(None, None, MDBX_PREV_NODUP)
} }
@ -264,7 +283,7 @@ where
/// Position at specified key. /// Position at specified key.
pub fn set<Value>(&mut self, key: &[u8]) -> Result<Option<Value>> pub fn set<Value>(&mut self, key: &[u8]) -> Result<Option<Value>>
where where
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_value(Some(key), None, MDBX_SET) self.get_value(Some(key), None, MDBX_SET)
} }
@ -272,8 +291,8 @@ where
/// Position at specified key, return both key and data. /// Position at specified key, return both key and data.
pub fn set_key<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>> pub fn set_key<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(Some(key), None, MDBX_SET_KEY) self.get_full(Some(key), None, MDBX_SET_KEY)
} }
@ -281,8 +300,8 @@ where
/// Position at first key greater than or equal to specified key. /// Position at first key greater than or equal to specified key.
pub fn set_range<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>> pub fn set_range<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(Some(key), None, MDBX_SET_RANGE) self.get_full(Some(key), None, MDBX_SET_RANGE)
} }
@ -291,8 +310,8 @@ where
/// duplicate data items. /// duplicate data items.
pub fn prev_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>> pub fn prev_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
self.get_full(None, None, MDBX_PREV_MULTIPLE) self.get_full(None, None, MDBX_PREV_MULTIPLE)
} }
@ -308,8 +327,8 @@ where
/// exactly and [true] if the next pair was returned. /// exactly and [true] if the next pair was returned.
pub fn set_lowerbound<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(bool, Key, Value)>> pub fn set_lowerbound<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(bool, Key, Value)>>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
let (k, v, found) = mdbx_try_optional!(self.get(Some(key), None, MDBX_SET_LOWERBOUND)); let (k, v, found) = mdbx_try_optional!(self.get(Some(key), None, MDBX_SET_LOWERBOUND));
@ -323,11 +342,11 @@ where
/// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the
/// duplicate data items of each key will be returned before moving on to /// duplicate data items of each key will be returned before moving on to
/// the next key. /// the next key.
pub fn iter<Key, Value>(&mut self) -> Iter<'txn, '_, K, Key, Value> pub fn iter<Key, Value>(&mut self) -> Iter<'_, K, Key, Value>
where where
Self: Sized, Self: Sized,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT) Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT)
} }
@ -337,11 +356,11 @@ where
/// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the
/// duplicate data items of each key will be returned before moving on to /// duplicate data items of each key will be returned before moving on to
/// the next key. /// the next key.
pub fn iter_start<Key, Value>(&mut self) -> Iter<'txn, '_, K, Key, Value> pub fn iter_start<Key, Value>(&mut self) -> Iter<'_, K, Key, Value>
where where
Self: Sized, Self: Sized,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
Iter::new(self, ffi::MDBX_FIRST, ffi::MDBX_NEXT) Iter::new(self, ffi::MDBX_FIRST, ffi::MDBX_NEXT)
} }
@ -351,10 +370,10 @@ where
/// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the
/// duplicate data items of each key will be returned before moving on to /// duplicate data items of each key will be returned before moving on to
/// the next key. /// the next key.
pub fn iter_from<Key, Value>(&mut self, key: &[u8]) -> Iter<'txn, '_, K, Key, Value> pub fn iter_from<Key, Value>(&mut self, key: &[u8]) -> Iter<'_, K, Key, Value>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
let res: Result<Option<((), ())>> = self.set_range(key); let res: Result<Option<((), ())>> = self.set_range(key);
if let Err(error) = res { if let Err(error) = res {
@ -366,30 +385,30 @@ where
/// Iterate over duplicate database items. The iterator will begin with the /// Iterate over duplicate database items. The iterator will begin with the
/// item next after the cursor, and continue until the end of the database. /// item next after the cursor, and continue until the end of the database.
/// Each item will be returned as an iterator of its duplicates. /// Each item will be returned as an iterator of its duplicates.
pub fn iter_dup<Key, Value>(&mut self) -> IterDup<'txn, '_, K, Key, Value> pub fn iter_dup<Key, Value>(&mut self) -> IterDup<'_, K, Key, Value>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
IterDup::new(self, ffi::MDBX_NEXT) IterDup::new(self, ffi::MDBX_NEXT)
} }
/// Iterate over duplicate database items starting from the beginning of the /// Iterate over duplicate database items starting from the beginning of the
/// database. Each item will be returned as an iterator of its duplicates. /// database. Each item will be returned as an iterator of its duplicates.
pub fn iter_dup_start<Key, Value>(&mut self) -> IterDup<'txn, '_, K, Key, Value> pub fn iter_dup_start<Key, Value>(&mut self) -> IterDup<'_, K, Key, Value>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
IterDup::new(self, ffi::MDBX_FIRST) IterDup::new(self, ffi::MDBX_FIRST)
} }
/// Iterate over duplicate items in the database starting from the given /// Iterate over duplicate items in the database starting from the given
/// key. Each item will be returned as an iterator of its duplicates. /// key. Each item will be returned as an iterator of its duplicates.
pub fn iter_dup_from<Key, Value>(&mut self, key: &[u8]) -> IterDup<'txn, '_, K, Key, Value> pub fn iter_dup_from<Key, Value>(&mut self, key: &[u8]) -> IterDup<'_, K, Key, Value>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
let res: Result<Option<((), ())>> = self.set_range(key); let res: Result<Option<((), ())>> = self.set_range(key);
if let Err(error) = res { if let Err(error) = res {
@ -399,10 +418,10 @@ where
} }
/// Iterate over the duplicates of the item in the database with the given key. /// Iterate over the duplicates of the item in the database with the given key.
pub fn iter_dup_of<Key, Value>(&mut self, key: &[u8]) -> Iter<'txn, '_, K, Key, Value> pub fn iter_dup_of<Key, Value>(&mut self, key: &[u8]) -> Iter<'_, K, Key, Value>
where where
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
let res: Result<Option<()>> = self.set(key); let res: Result<Option<()>> = self.set(key);
match res { match res {
@ -417,7 +436,7 @@ where
} }
} }
impl<'txn> Cursor<'txn, RW> { impl Cursor<RW> {
/// Puts a key/data pair into the database. The cursor will be positioned at /// Puts a key/data pair into the database. The cursor will be positioned at
/// the new data item, or on failure usually near it. /// the new data item, or on failure usually near it.
pub fn put(&mut self, key: &[u8], data: &[u8], flags: WriteFlags) -> Result<()> { pub fn put(&mut self, key: &[u8], data: &[u8], flags: WriteFlags) -> Result<()> {
@ -449,7 +468,7 @@ impl<'txn> Cursor<'txn, RW> {
} }
} }
impl<'txn, K> Clone for Cursor<'txn, K> impl<K> Clone for Cursor<K>
where where
K: TransactionKind, K: TransactionKind,
{ {
@ -458,7 +477,7 @@ where
} }
} }
impl<'txn, K> fmt::Debug for Cursor<'txn, K> impl<K> fmt::Debug for Cursor<K>
where where
K: TransactionKind, K: TransactionKind,
{ {
@ -467,7 +486,7 @@ where
} }
} }
impl<'txn, K> Drop for Cursor<'txn, K> impl<K> Drop for Cursor<K>
where where
K: TransactionKind, K: TransactionKind,
{ {
@ -485,28 +504,16 @@ unsafe fn slice_to_val(slice: Option<&[u8]>) -> ffi::MDBX_val {
} }
} }
unsafe impl<'txn, K> Send for Cursor<'txn, K> where K: TransactionKind {} unsafe impl<K> Send for Cursor<K> where K: TransactionKind {}
unsafe impl<'txn, K> Sync for Cursor<'txn, K> where K: TransactionKind {} unsafe impl<K> Sync for Cursor<K> where K: TransactionKind {}
impl<'txn, K> IntoIterator for Cursor<'txn, K>
where
K: TransactionKind,
{
type Item = Result<(Cow<'txn, [u8]>, Cow<'txn, [u8]>)>;
type IntoIter = IntoIter<'txn, K, Cow<'txn, [u8]>, Cow<'txn, [u8]>>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self, MDBX_NEXT, MDBX_NEXT)
}
}
/// An iterator over the key/value pairs in an MDBX database. /// An iterator over the key/value pairs in an MDBX database.
#[derive(Debug)] #[derive(Debug)]
pub enum IntoIter<'txn, K, Key, Value> pub enum IntoIter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// An iterator that returns an error on every call to [Iter::next()]. /// An iterator that returns an error on every call to [Iter::next()].
/// Cursor.iter*() creates an Iter of this type when MDBX returns an error /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
@ -521,7 +528,7 @@ where
/// fails for some reason. /// fails for some reason.
Ok { Ok {
/// The MDBX cursor with which to iterate. /// The MDBX cursor with which to iterate.
cursor: Cursor<'txn, K>, cursor: Cursor<K>,
/// The first operation to perform when the consumer calls [Iter::next()]. /// The first operation to perform when the consumer calls [Iter::next()].
op: ffi::MDBX_cursor_op, op: ffi::MDBX_cursor_op,
@ -529,33 +536,33 @@ where
/// The next and subsequent operations to perform. /// The next and subsequent operations to perform.
next_op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op,
_marker: PhantomData<fn(&'txn (), K, Key, Value)>, _marker: PhantomData<fn(&'cur (), K, Key, Value)>,
}, },
} }
impl<'txn, K, Key, Value> IntoIter<'txn, K, Key, Value> impl<'cur, K, Key, Value> IntoIter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// Creates a new iterator backed by the given cursor. /// Creates a new iterator backed by the given cursor.
fn new(cursor: Cursor<'txn, K>, op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op) -> Self { fn new(cursor: Cursor<K>, op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op) -> Self {
IntoIter::Ok { cursor, op, next_op, _marker: PhantomData } IntoIter::Ok { cursor, op, next_op, _marker: Default::default() }
} }
} }
impl<'txn, K, Key, Value> Iterator for IntoIter<'txn, K, Key, Value> impl<'cur, K, Key, Value> Iterator for IntoIter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
type Item = Result<(Key, Value)>; type Item = Result<(Key, Value)>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
match self { match self {
Self::Ok { cursor, op, next_op, _marker } => { Self::Ok { cursor, op, next_op, .. } => {
let mut key = ffi::MDBX_val { iov_len: 0, iov_base: ptr::null_mut() }; let mut key = ffi::MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };
let mut data = ffi::MDBX_val { iov_len: 0, iov_base: ptr::null_mut() }; let mut data = ffi::MDBX_val { iov_len: 0, iov_base: ptr::null_mut() };
let op = mem::replace(op, *next_op); let op = mem::replace(op, *next_op);
@ -589,11 +596,11 @@ where
/// An iterator over the key/value pairs in an MDBX database. /// An iterator over the key/value pairs in an MDBX database.
#[derive(Debug)] #[derive(Debug)]
pub enum Iter<'txn, 'cur, K, Key, Value> pub enum Iter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// An iterator that returns an error on every call to [Iter::next()]. /// An iterator that returns an error on every call to [Iter::next()].
/// Cursor.iter*() creates an Iter of this type when MDBX returns an error /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
@ -608,7 +615,7 @@ where
/// fails for some reason. /// fails for some reason.
Ok { Ok {
/// The MDBX cursor with which to iterate. /// The MDBX cursor with which to iterate.
cursor: &'cur mut Cursor<'txn, K>, cursor: &'cur mut Cursor<K>,
/// The first operation to perform when the consumer calls [Iter::next()]. /// The first operation to perform when the consumer calls [Iter::next()].
op: ffi::MDBX_cursor_op, op: ffi::MDBX_cursor_op,
@ -616,31 +623,31 @@ where
/// The next and subsequent operations to perform. /// The next and subsequent operations to perform.
next_op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op,
_marker: PhantomData<fn(&'txn (Key, Value))>, _marker: PhantomData<fn(&'cur (), K, Key, Value)>,
}, },
} }
impl<'txn, 'cur, K, Key, Value> Iter<'txn, 'cur, K, Key, Value> impl<'cur, K, Key, Value> Iter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// Creates a new iterator backed by the given cursor. /// Creates a new iterator backed by the given cursor.
fn new( fn new(
cursor: &'cur mut Cursor<'txn, K>, cursor: &'cur mut Cursor<K>,
op: ffi::MDBX_cursor_op, op: ffi::MDBX_cursor_op,
next_op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op,
) -> Self { ) -> Self {
Iter::Ok { cursor, op, next_op, _marker: PhantomData } Iter::Ok { cursor, op, next_op, _marker: Default::default() }
} }
} }
impl<'txn, 'cur, K, Key, Value> Iterator for Iter<'txn, 'cur, K, Key, Value> impl<'cur, K, Key, Value> Iterator for Iter<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
type Item = Result<(Key, Value)>; type Item = Result<(Key, Value)>;
@ -682,11 +689,11 @@ where
/// ///
/// The yielded items of the iterator are themselves iterators over the duplicate values for a /// The yielded items of the iterator are themselves iterators over the duplicate values for a
/// specific key. /// specific key.
pub enum IterDup<'txn, 'cur, K, Key, Value> pub enum IterDup<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// An iterator that returns an error on every call to Iter.next(). /// An iterator that returns an error on every call to Iter.next().
/// Cursor.iter*() creates an Iter of this type when MDBX returns an error /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
@ -701,45 +708,45 @@ where
/// fails for some reason. /// fails for some reason.
Ok { Ok {
/// The MDBX cursor with which to iterate. /// The MDBX cursor with which to iterate.
cursor: &'cur mut Cursor<'txn, K>, cursor: &'cur mut Cursor<K>,
/// The first operation to perform when the consumer calls Iter.next(). /// The first operation to perform when the consumer calls Iter.next().
op: MDBX_cursor_op, op: MDBX_cursor_op,
_marker: PhantomData<fn(&'txn (Key, Value))>, _marker: PhantomData<fn(&'cur (Key, Value))>,
}, },
} }
impl<'txn, 'cur, K, Key, Value> IterDup<'txn, 'cur, K, Key, Value> impl<'cur, K, Key, Value> IterDup<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
/// Creates a new iterator backed by the given cursor. /// Creates a new iterator backed by the given cursor.
fn new(cursor: &'cur mut Cursor<'txn, K>, op: MDBX_cursor_op) -> Self { fn new(cursor: &'cur mut Cursor<K>, op: MDBX_cursor_op) -> Self {
IterDup::Ok { cursor, op, _marker: PhantomData } IterDup::Ok { cursor, op, _marker: Default::default() }
} }
} }
impl<'txn, 'cur, K, Key, Value> fmt::Debug for IterDup<'txn, 'cur, K, Key, Value> impl<'cur, K, Key, Value> fmt::Debug for IterDup<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IterDup").finish() f.debug_struct("IterDup").finish()
} }
} }
impl<'txn, 'cur, K, Key, Value> Iterator for IterDup<'txn, 'cur, K, Key, Value> impl<'cur, K, Key, Value> Iterator for IterDup<'cur, K, Key, Value>
where where
K: TransactionKind, K: TransactionKind,
Key: TableObject<'txn>, Key: TableObject,
Value: TableObject<'txn>, Value: TableObject,
{ {
type Item = IntoIter<'txn, K, Key, Value>; type Item = IntoIter<'cur, K, Key, Value>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
match self { match self {

View File

@ -208,7 +208,7 @@ impl Environment {
let db = Database::freelist_db(); let db = Database::freelist_db();
let cursor = txn.cursor(&db)?; let cursor = txn.cursor(&db)?;
for result in cursor { for result in cursor.into_iter_slices() {
let (_key, value) = result?; let (_key, value) = result?;
if value.len() < size_of::<usize>() { if value.len() < size_of::<usize>() {
return Err(Error::Corrupted) return Err(Error::Corrupted)

View File

@ -107,11 +107,6 @@ where
self.inner.txn_execute(f) self.inner.txn_execute(f)
} }
/// Returns a copy of the pointer to the underlying MDBX transaction.
pub(crate) fn txn_ptr(&self) -> TransactionPtr {
self.inner.txn.clone()
}
/// Returns a copy of the raw pointer to the underlying MDBX transaction. /// Returns a copy of the raw pointer to the underlying MDBX transaction.
#[doc(hidden)] #[doc(hidden)]
pub fn txn(&self) -> *mut ffi::MDBX_txn { pub fn txn(&self) -> *mut ffi::MDBX_txn {
@ -151,9 +146,9 @@ where
/// returned. Retrieval of other items requires the use of /// returned. Retrieval of other items requires the use of
/// [Cursor]. If the item is not in the database, then /// [Cursor]. If the item is not in the database, then
/// [None] will be returned. /// [None] will be returned.
pub fn get<'txn, Key>(&'txn self, dbi: ffi::MDBX_dbi, key: &[u8]) -> Result<Option<Key>> pub fn get<Key>(&self, dbi: ffi::MDBX_dbi, key: &[u8]) -> Result<Option<Key>>
where where
Key: TableObject<'txn>, Key: TableObject,
{ {
let key_val: ffi::MDBX_val = let key_val: ffi::MDBX_val =
ffi::MDBX_val { iov_len: key.len(), iov_base: key.as_ptr() as *mut c_void }; ffi::MDBX_val { iov_len: key.len(), iov_base: key.as_ptr() as *mut c_void };
@ -257,13 +252,31 @@ where
} }
/// Open a new cursor on the given database. /// Open a new cursor on the given database.
pub fn cursor(&self, db: &Database) -> Result<Cursor<'_, K>> { pub fn cursor(&self, db: &Database) -> Result<Cursor<K>> {
Cursor::new(self, db.dbi()) Cursor::new(self.clone(), db.dbi())
} }
/// Open a new cursor on the given dbi. /// Open a new cursor on the given dbi.
pub fn cursor_with_dbi(&self, dbi: ffi::MDBX_dbi) -> Result<Cursor<'_, K>> { pub fn cursor_with_dbi(&self, dbi: ffi::MDBX_dbi) -> Result<Cursor<K>> {
Cursor::new(self, dbi) Cursor::new(self.clone(), dbi)
}
}
impl<K> Clone for Transaction<K>
where
K: TransactionKind,
{
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
}
impl<K> fmt::Debug for Transaction<K>
where
K: TransactionKind,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RoTransaction").finish_non_exhaustive()
} }
} }
@ -499,15 +512,6 @@ impl Transaction<RW> {
} }
} }
impl<K> fmt::Debug for Transaction<K>
where
K: TransactionKind,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RoTransaction").finish_non_exhaustive()
}
}
/// A shareable pointer to an MDBX transaction. /// A shareable pointer to an MDBX transaction.
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct TransactionPtr { pub(crate) struct TransactionPtr {