#[cfg(feature = "experimental-api-5")]
use crate::KeyRange;
use crate::db::TransactionGuard;
use crate::sealed::Sealed;
use crate::sync::Mutex;
#[cfg(feature = "experimental-api-5")]
use crate::tree_store::BtreeCursor;
#[cfg(feature = "experimental_cursor")]
use crate::tree_store::BtreeCursorMut;
#[cfg(not(feature = "experimental-api-5"))]
use crate::tree_store::encode_bounds;
use crate::tree_store::{
AccessGuardMutInPlace, Btree, BtreeCursorRange, BtreeExtractIf, BtreeHeader, BtreeMut,
MAX_PAIR_LENGTH, MAX_VALUE_LENGTH, PageAllocator, PageHint, PageNumber, PageResolver,
PageTracker, RawBtree,
};
use crate::types::{Key, MutInPlaceValue, Value};
use crate::{AccessGuard, AccessGuardMut, StorageError, WriteTransaction};
use crate::{Result, TableHandle};
use alloc::string::String;
use alloc::string::ToString;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::borrow::Borrow;
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::ops::Bound;
#[cfg(not(feature = "experimental-api-5"))]
use core::ops::RangeBounds;
#[derive(Debug)]
pub struct TableStats {
pub(crate) tree_height: u32,
pub(crate) leaf_pages: u64,
pub(crate) branch_pages: u64,
pub(crate) stored_leaf_bytes: u64,
pub(crate) metadata_bytes: u64,
pub(crate) fragmented_bytes: u64,
}
impl TableStats {
pub fn tree_height(&self) -> u32 {
self.tree_height
}
pub fn leaf_pages(&self) -> u64 {
self.leaf_pages
}
pub fn branch_pages(&self) -> u64 {
self.branch_pages
}
pub fn stored_bytes(&self) -> u64 {
self.stored_leaf_bytes
}
pub fn metadata_bytes(&self) -> u64 {
self.metadata_bytes
}
pub fn fragmented_bytes(&self) -> u64 {
self.fragmented_bytes
}
}
pub struct Table<'txn, K: Key + 'static, V: Value + 'static> {
name: String,
transaction: &'txn WriteTransaction,
tree: BtreeMut<K, V>,
}
impl<K: Key + 'static, V: Value + 'static> TableHandle for Table<'_, K, V> {
fn name(&self) -> &str {
&self.name
}
}
struct RetainPanicGuard<'txn> {
transaction: &'txn WriteTransaction,
disarmed: bool,
}
impl<'txn> RetainPanicGuard<'txn> {
fn new(transaction: &'txn WriteTransaction) -> Self {
Self {
transaction,
disarmed: false,
}
}
fn disarm(&mut self) {
self.disarmed = true;
}
}
impl Drop for RetainPanicGuard<'_> {
fn drop(&mut self) {
if !self.disarmed && crate::panicking() {
self.transaction.poison();
}
}
}
impl<'txn, K: Key + 'static, V: Value + 'static> Table<'txn, K, V> {
pub(crate) fn new(
name: &str,
table_root: Option<BtreeHeader>,
freed_pages: Arc<Mutex<Vec<PageNumber>>>,
allocated_pages: Arc<PageTracker>,
page_allocator: PageAllocator,
transaction: &'txn WriteTransaction,
) -> Table<'txn, K, V> {
Table {
name: name.to_string(),
transaction,
tree: BtreeMut::new(
table_root,
transaction.transaction_guard(),
page_allocator,
freed_pages,
allocated_pages,
),
}
}
#[allow(dead_code)]
#[cfg(not(redb_no_std))]
pub(crate) fn print_debug(&self, include_values: bool) -> Result {
self.tree.print_debug(include_values)
}
pub fn get_mut<'k>(
&mut self,
key: impl Borrow<K::SelfType<'k>>,
) -> Result<Option<AccessGuardMut<'_, V>>> {
self.tree.get_mut(key.borrow())
}
pub fn pop_first(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.pop_first()
}
pub fn pop_last(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.pop_last()
}
pub fn extract_if<F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
predicate: F,
) -> Result<ExtractIf<'_, K, V, F>> {
self.extract_in_bounds(Bound::Unbounded, Bound::Unbounded, predicate)
}
#[cfg(feature = "experimental-api-5")]
pub fn extract_from_if<'a, F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
range: impl KeyRange<'a, K>,
predicate: F,
) -> Result<ExtractIf<'_, K, V, F>> {
let (lower, upper) = range.key_bounds();
self.extract_in_bounds(lower, upper, predicate)
}
#[cfg(not(feature = "experimental-api-5"))]
pub fn extract_from_if<'a, KR, F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
range: impl RangeBounds<KR> + 'a,
predicate: F,
) -> Result<ExtractIf<'_, K, V, F>>
where
KR: Borrow<K::SelfType<'a>> + 'a,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
self.extract_in_bounds(lower, upper, predicate)
}
fn range_in_bounds(
&self,
lower: Bound<Vec<u8>>,
upper: Bound<Vec<u8>>,
) -> Result<Range<'_, K, V>> {
self.tree
.range_bounds(lower, upper)
.map(|x| Range::new(x, self.transaction.transaction_guard()))
}
fn extract_in_bounds<F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
lower: Bound<Vec<u8>>,
upper: Bound<Vec<u8>>,
predicate: F,
) -> Result<ExtractIf<'_, K, V, F>> {
let inner = self.tree.extract_from_bounds(lower, upper, predicate)?;
Ok(ExtractIf::new(inner, Some(self.transaction)))
}
pub fn retain<F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
predicate: F,
) -> Result {
self.retain_in_bounds(Bound::Unbounded, Bound::Unbounded, predicate)
}
#[cfg(feature = "experimental-api-5")]
pub fn retain_in<'a, F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
range: impl KeyRange<'a, K>,
predicate: F,
) -> Result {
let (lower, upper) = range.key_bounds();
self.retain_in_bounds(lower, upper, predicate)
}
#[cfg(not(feature = "experimental-api-5"))]
pub fn retain_in<'a, KR, F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
range: impl RangeBounds<KR> + 'a,
predicate: F,
) -> Result
where
KR: Borrow<K::SelfType<'a>> + 'a,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
self.retain_in_bounds(lower, upper, predicate)
}
fn retain_in_bounds<F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool>(
&mut self,
lower: Bound<Vec<u8>>,
upper: Bound<Vec<u8>>,
predicate: F,
) -> Result {
let mut panic_guard = RetainPanicGuard::new(self.transaction);
let mut poisoned = false;
let result = self
.tree
.retain_in_bounds(predicate, lower, upper, &mut poisoned);
panic_guard.disarm();
if poisoned {
self.transaction.poison();
}
result
}
pub fn insert<'k, 'v>(
&mut self,
key: impl Borrow<K::SelfType<'k>>,
value: impl Borrow<V::SelfType<'v>>,
) -> Result<Option<AccessGuard<'_, V>>> {
let value_len = V::as_bytes(value.borrow()).as_ref().len();
if value_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(value_len));
}
let key_len = K::as_bytes(key.borrow()).as_ref().len();
if key_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(key_len));
}
if value_len + key_len > MAX_PAIR_LENGTH {
return Err(StorageError::ValueTooLarge(value_len + key_len));
}
self.tree.insert(key.borrow(), value.borrow())
}
pub fn remove<'a>(
&mut self,
key: impl Borrow<K::SelfType<'a>>,
) -> Result<Option<AccessGuard<'_, V>>> {
self.tree.remove(key.borrow())
}
#[cfg(feature = "experimental_cursor")]
pub fn lower_bound_mut<'a>(
&mut self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<CursorMut<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor_mut();
inner.seek_lower_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(CursorMut::new(inner, self.transaction))
}
#[cfg(feature = "experimental_cursor")]
pub fn upper_bound_mut<'a>(
&mut self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<CursorMut<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor_mut();
inner.seek_upper_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(CursorMut::new(inner, self.transaction))
}
pub fn entry<'a>(&'a mut self, key: K::SelfType<'a>) -> Result<Entry<'a, K, V>> {
let key_len = K::as_bytes(&key).as_ref().len();
if key_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(key_len));
}
if self.tree.get(&key)?.is_some() {
Ok(Entry::Occupied(OccupiedEntry {
tree: &mut self.tree,
key,
}))
} else {
Ok(Entry::Vacant(VacantEntry {
tree: &mut self.tree,
key,
}))
}
}
}
impl<K: Key + 'static, V: MutInPlaceValue + 'static> Table<'_, K, V> {
pub fn insert_reserve<'a>(
&mut self,
key: impl Borrow<K::SelfType<'a>>,
value_length: usize,
) -> Result<AccessGuardMutInPlace<'_, V>> {
if value_length > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(value_length));
}
let key_len = K::as_bytes(key.borrow()).as_ref().len();
if key_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(key_len));
}
if value_length + key_len > MAX_PAIR_LENGTH {
return Err(StorageError::ValueTooLarge(value_length + key_len));
}
self.tree.insert_reserve(key.borrow(), value_length)
}
}
impl<K: Key + 'static, V: Value + 'static> ReadableTableMetadata for Table<'_, K, V> {
fn stats(&self) -> Result<TableStats> {
let tree_stats = self.tree.stats()?;
Ok(TableStats {
tree_height: tree_stats.tree_height,
leaf_pages: tree_stats.leaf_pages,
branch_pages: tree_stats.branch_pages,
stored_leaf_bytes: tree_stats.stored_leaf_bytes,
metadata_bytes: tree_stats.metadata_bytes,
fragmented_bytes: tree_stats.fragmented_bytes,
})
}
fn len(&self) -> Result<u64> {
self.tree.len()
}
}
impl<K: Key + 'static, V: Value + 'static> ReadableTable<K, V> for Table<'_, K, V> {
fn get<'a>(&self, key: impl Borrow<K::SelfType<'a>>) -> Result<Option<AccessGuard<'_, V>>> {
self.tree.get(key.borrow())
}
#[cfg(feature = "experimental-api-5")]
fn range<'a>(&self, range: impl KeyRange<'a, K>) -> Result<Range<'_, K, V>> {
let (lower, upper) = range.key_bounds();
self.range_in_bounds(lower, upper)
}
#[cfg(not(feature = "experimental-api-5"))]
fn range<'a, KR>(&self, range: impl RangeBounds<KR> + 'a) -> Result<Range<'_, K, V>>
where
KR: Borrow<K::SelfType<'a>> + 'a,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
self.range_in_bounds(lower, upper)
}
fn first(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.first()
}
fn last(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.last()
}
#[cfg(feature = "experimental-api-5")]
fn lower_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor()?;
inner.seek_lower_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(Cursor::new(inner, self.transaction.transaction_guard()))
}
#[cfg(feature = "experimental-api-5")]
fn upper_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor()?;
inner.seek_upper_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(Cursor::new(inner, self.transaction.transaction_guard()))
}
}
impl<K: Key, V: Value> Sealed for Table<'_, K, V> {}
impl<K: Key + 'static, V: Value + 'static> Drop for Table<'_, K, V> {
fn drop(&mut self) {
self.transaction.close_table(
&self.name,
&self.tree,
self.tree.get_root().map(|x| x.length).unwrap_or_default(),
);
}
}
fn debug_helper<K: Key + 'static, V: Value + 'static>(
f: &mut Formatter<'_>,
name: &str,
len: Result<u64>,
first: Result<Option<(AccessGuard<K>, AccessGuard<V>)>>,
last: Result<Option<(AccessGuard<K>, AccessGuard<V>)>>,
) -> core::fmt::Result {
write!(f, "Table [ name: \"{name}\", ")?;
if let Ok(len) = len {
if len == 0 {
write!(f, "No entries")?;
} else if len == 1 {
if let Ok(first) = first {
let (key, value) = first.as_ref().unwrap();
write!(f, "One key-value: {:?} = {:?}", key.value(), value.value())?;
} else {
write!(f, "I/O Error accessing table!")?;
}
} else {
if let Ok(first) = first {
let (key, value) = first.as_ref().unwrap();
write!(f, "first: {:?} = {:?}, ", key.value(), value.value())?;
} else {
write!(f, "I/O Error accessing table!")?;
}
if len > 2 {
write!(f, "...{} more entries..., ", len - 2)?;
}
if let Ok(last) = last {
let (key, value) = last.as_ref().unwrap();
write!(f, "last: {:?} = {:?}", key.value(), value.value())?;
} else {
write!(f, "I/O Error accessing table!")?;
}
}
} else {
write!(f, "I/O Error accessing table!")?;
}
write!(f, " ]")?;
Ok(())
}
impl<K: Key + 'static, V: Value + 'static> Debug for Table<'_, K, V> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
debug_helper(f, &self.name, self.len(), self.first(), self.last())
}
}
pub trait ReadableTableMetadata {
fn stats(&self) -> Result<TableStats>;
fn len(&self) -> Result<u64>;
fn is_empty(&self) -> Result<bool> {
Ok(self.len()? == 0)
}
}
pub trait ReadableTable<K: Key + 'static, V: Value + 'static>: ReadableTableMetadata {
fn get<'a>(&self, key: impl Borrow<K::SelfType<'a>>) -> Result<Option<AccessGuard<'_, V>>>;
#[cfg(feature = "experimental-api-5")]
fn range<'a>(&self, range: impl KeyRange<'a, K>) -> Result<Range<'_, K, V>>;
#[cfg(not(feature = "experimental-api-5"))]
fn range<'a, KR>(&self, range: impl RangeBounds<KR> + 'a) -> Result<Range<'_, K, V>>
where
KR: Borrow<K::SelfType<'a>> + 'a;
fn first(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>>;
fn last(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>>;
#[cfg_attr(feature = "experimental_cursor", doc = "```rust")]
#[cfg_attr(not(feature = "experimental_cursor"), doc = "```rust,ignore")]
#[cfg(feature = "experimental-api-5")]
fn lower_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>>;
#[cfg(feature = "experimental-api-5")]
fn upper_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>>;
fn iter(&self) -> Result<Range<'_, K, V>> {
#[cfg(feature = "experimental-api-5")]
let range = self.range(..);
#[cfg(not(feature = "experimental-api-5"))]
let range = self.range::<K::SelfType<'_>>(..);
range
}
}
pub struct ReadOnlyUntypedTable {
name: String,
tree: RawBtree,
}
impl Sealed for ReadOnlyUntypedTable {}
impl TableHandle for ReadOnlyUntypedTable {
fn name(&self) -> &str {
&self.name
}
}
impl ReadableTableMetadata for ReadOnlyUntypedTable {
fn stats(&self) -> Result<TableStats> {
let tree_stats = self.tree.stats()?;
Ok(TableStats {
tree_height: tree_stats.tree_height,
leaf_pages: tree_stats.leaf_pages,
branch_pages: tree_stats.branch_pages,
stored_leaf_bytes: tree_stats.stored_leaf_bytes,
metadata_bytes: tree_stats.metadata_bytes,
fragmented_bytes: tree_stats.fragmented_bytes,
})
}
fn len(&self) -> Result<u64> {
self.tree.len()
}
}
impl ReadOnlyUntypedTable {
pub(crate) fn new(
name: &str,
root_page: Option<BtreeHeader>,
hint: PageHint,
fixed_key_size: Option<usize>,
fixed_value_size: Option<usize>,
mem: PageResolver,
) -> Self {
Self {
name: name.to_string(),
tree: RawBtree::new(root_page, fixed_key_size, fixed_value_size, mem, hint),
}
}
}
pub struct ReadOnlyTable<K: Key + 'static, V: Value + 'static> {
name: String,
tree: Btree<K, V>,
transaction_guard: Arc<TransactionGuard>,
}
impl<K: Key + 'static, V: Value + 'static> TableHandle for ReadOnlyTable<K, V> {
fn name(&self) -> &str {
&self.name
}
}
impl<K: Key + 'static, V: Value + 'static> ReadOnlyTable<K, V> {
pub(crate) fn new(
name: String,
root_page: Option<BtreeHeader>,
hint: PageHint,
guard: Arc<TransactionGuard>,
mem: PageResolver,
) -> Result<ReadOnlyTable<K, V>> {
Ok(ReadOnlyTable {
name,
tree: Btree::new(root_page, hint, guard.clone(), mem)?,
transaction_guard: guard,
})
}
#[cfg(not(feature = "experimental-api-5"))]
pub fn get<'a>(
&self,
key: impl Borrow<K::SelfType<'a>>,
) -> Result<Option<AccessGuard<'static, V>>> {
self.tree.get(key.borrow())
}
pub fn get_owned<'a>(
&self,
key: impl Borrow<K::SelfType<'a>>,
) -> Result<Option<OwnedAccessGuard<V>>> {
Ok(self
.tree
.get(key.borrow())?
.map(|x| OwnedAccessGuard::new(x, self.transaction_guard.clone())))
}
#[cfg(not(feature = "experimental-api-5"))]
pub fn range<'a, KR>(&self, range: impl RangeBounds<KR>) -> Result<Range<'static, K, V>>
where
KR: Borrow<K::SelfType<'a>>,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
self.range_in_bounds(lower, upper)
}
fn range_in_bounds(
&self,
lower: Bound<Vec<u8>>,
upper: Bound<Vec<u8>>,
) -> Result<Range<'static, K, V>> {
self.tree
.range_bounds(lower, upper)
.map(|x| Range::new(x, self.transaction_guard.clone()))
}
#[cfg(feature = "experimental-api-5")]
pub fn range_owned<'a>(&self, range: impl KeyRange<'a, K>) -> Result<OwnedRange<K, V>> {
let (lower, upper) = range.key_bounds();
Ok(OwnedRange::new(
self.range_in_bounds(lower, upper)?,
self.transaction_guard.clone(),
))
}
#[cfg(not(feature = "experimental-api-5"))]
pub fn range_owned<'a, KR>(&self, range: impl RangeBounds<KR>) -> Result<OwnedRange<K, V>>
where
KR: Borrow<K::SelfType<'a>>,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
Ok(OwnedRange::new(
self.range_in_bounds(lower, upper)?,
self.transaction_guard.clone(),
))
}
}
impl<K: Key + 'static, V: Value + 'static> ReadableTableMetadata for ReadOnlyTable<K, V> {
fn stats(&self) -> Result<TableStats> {
let tree_stats = self.tree.stats()?;
Ok(TableStats {
tree_height: tree_stats.tree_height,
leaf_pages: tree_stats.leaf_pages,
branch_pages: tree_stats.branch_pages,
stored_leaf_bytes: tree_stats.stored_leaf_bytes,
metadata_bytes: tree_stats.metadata_bytes,
fragmented_bytes: tree_stats.fragmented_bytes,
})
}
fn len(&self) -> Result<u64> {
self.tree.len()
}
}
impl<K: Key + 'static, V: Value + 'static> ReadableTable<K, V> for ReadOnlyTable<K, V> {
fn get<'a>(&self, key: impl Borrow<K::SelfType<'a>>) -> Result<Option<AccessGuard<'_, V>>> {
self.tree.get(key.borrow())
}
#[cfg(feature = "experimental-api-5")]
fn range<'a>(&self, range: impl KeyRange<'a, K>) -> Result<Range<'_, K, V>> {
let (lower, upper) = range.key_bounds();
self.range_in_bounds(lower, upper)
}
#[cfg(not(feature = "experimental-api-5"))]
fn range<'a, KR>(&self, range: impl RangeBounds<KR> + 'a) -> Result<Range<'_, K, V>>
where
KR: Borrow<K::SelfType<'a>> + 'a,
{
let (lower, upper) = encode_bounds::<K, KR, _>(&range);
self.range_in_bounds(lower, upper)
}
fn first(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.first()
}
fn last(&self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.tree.last()
}
#[cfg(feature = "experimental-api-5")]
fn lower_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor();
inner.seek_lower_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(Cursor::new(inner, self.transaction_guard.clone()))
}
#[cfg(feature = "experimental-api-5")]
fn upper_bound<'a>(
&self,
bound: Bound<impl Borrow<K::SelfType<'a>>>,
) -> Result<Cursor<'_, K, V>> {
let bound = bound_to_bytes::<K, _>(&bound);
let mut inner = self.tree.cursor();
inner.seek_upper_bound(bound.as_ref().map(|bytes| bytes.as_slice()))?;
Ok(Cursor::new(inner, self.transaction_guard.clone()))
}
}
impl<K: Key, V: Value> Sealed for ReadOnlyTable<K, V> {}
impl<K: Key + 'static, V: Value + 'static> Debug for ReadOnlyTable<K, V> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
debug_helper(f, &self.name, self.len(), self.first(), self.last())
}
}
pub struct ExtractIf<
'a,
K: Key + 'static,
V: Value + 'static,
F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool,
> {
inner: BtreeExtractIf<'a, K, V, F>,
poison_target: Option<&'a WriteTransaction>,
}
impl<
'a,
K: Key + 'static,
V: Value + 'static,
F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool,
> ExtractIf<'a, K, V, F>
{
pub(crate) fn new(
inner: BtreeExtractIf<'a, K, V, F>,
poison_target: Option<&'a WriteTransaction>,
) -> Self {
Self {
inner,
poison_target,
}
}
pub fn close(mut self) -> Result {
self.inner.close()
}
}
impl<
K: Key + 'static,
V: Value + 'static,
F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool,
> Drop for ExtractIf<'_, K, V, F>
{
fn drop(&mut self) {
let _ = self.inner.close();
if (self.inner.close_failed() || self.inner.predicate_panicked())
&& let Some(transaction) = self.poison_target
{
transaction.poison();
}
}
}
impl<
'a,
K: Key + 'static,
V: Value + 'static,
F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool,
> Iterator for ExtractIf<'a, K, V, F>
{
type Item = Result<(AccessGuard<'a, K>, AccessGuard<'a, V>)>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
impl<
K: Key + 'static,
V: Value + 'static,
F: for<'f> FnMut(K::SelfType<'f>, V::SelfType<'f>) -> bool,
> DoubleEndedIterator for ExtractIf<'_, K, V, F>
{
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
#[derive(Clone)]
pub struct Range<'a, K: Key + 'static, V: Value + 'static> {
inner: BtreeCursorRange<K, V>,
_transaction_guard: Arc<TransactionGuard>,
_lifetime: PhantomData<&'a ()>,
}
impl<K: Key + 'static, V: Value + 'static> Range<'_, K, V> {
pub(super) fn new(inner: BtreeCursorRange<K, V>, guard: Arc<TransactionGuard>) -> Self {
Self {
inner,
_transaction_guard: guard,
_lifetime: PhantomData,
}
}
}
impl<'a, K: Key + 'static, V: Value + 'static> Iterator for Range<'a, K, V> {
type Item = Result<(AccessGuard<'a, K>, AccessGuard<'a, V>)>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|x| {
x.map(|entry| {
let (page, key_range, value_range) = entry.into_raw();
let key = AccessGuard::with_page(page.clone(), key_range);
let value = AccessGuard::with_page(page, value_range);
(key, value)
})
})
}
}
impl<K: Key + 'static, V: Value + 'static> DoubleEndedIterator for Range<'_, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|x| {
x.map(|entry| {
let (page, key_range, value_range) = entry.into_raw();
let key = AccessGuard::with_page(page.clone(), key_range);
let value = AccessGuard::with_page(page, value_range);
(key, value)
})
})
}
}
pub struct OwnedAccessGuard<V: Value + 'static> {
inner: AccessGuard<'static, V>,
_transaction_guard: Arc<TransactionGuard>,
}
impl<V: Value + 'static> OwnedAccessGuard<V> {
pub(crate) fn new(inner: AccessGuard<'static, V>, guard: Arc<TransactionGuard>) -> Self {
Self {
inner,
_transaction_guard: guard,
}
}
pub fn value(&self) -> V::SelfType<'_> {
self.inner.value()
}
}
#[derive(Clone)]
pub struct OwnedRange<K: Key + 'static, V: Value + 'static> {
inner: Range<'static, K, V>,
transaction_guard: Arc<TransactionGuard>,
}
impl<K: Key + 'static, V: Value + 'static> OwnedRange<K, V> {
pub(super) fn new(inner: Range<'static, K, V>, guard: Arc<TransactionGuard>) -> Self {
Self {
inner,
transaction_guard: guard,
}
}
}
impl<K: Key + 'static, V: Value + 'static> Iterator for OwnedRange<K, V> {
type Item = Result<(OwnedAccessGuard<K>, OwnedAccessGuard<V>)>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|x| {
x.map(|(key, value)| {
(
OwnedAccessGuard::new(key, self.transaction_guard.clone()),
OwnedAccessGuard::new(value, self.transaction_guard.clone()),
)
})
})
}
}
impl<K: Key + 'static, V: Value + 'static> DoubleEndedIterator for OwnedRange<K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|x| {
x.map(|(key, value)| {
(
OwnedAccessGuard::new(key, self.transaction_guard.clone()),
OwnedAccessGuard::new(value, self.transaction_guard.clone()),
)
})
})
}
}
pub enum Entry<'a, K: Key + 'static, V: Value + 'static> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
impl<'a, K: Key + 'static, V: Value + 'static> Entry<'a, K, V> {
pub fn key(&self) -> &K::SelfType<'a> {
match self {
Entry::Occupied(entry) => entry.key(),
Entry::Vacant(entry) => entry.key(),
}
}
pub fn or_insert<'v>(
self,
default: impl Borrow<V::SelfType<'v>>,
) -> Result<AccessGuardMut<'a, V>> {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
pub fn or_insert_with<'v, F, B>(self, default: F) -> Result<AccessGuardMut<'a, V>>
where
F: FnOnce() -> B,
B: Borrow<V::SelfType<'v>>,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
pub fn or_insert_with_key<'v, F, B>(self, default: F) -> Result<AccessGuardMut<'a, V>>
where
F: FnOnce(&K::SelfType<'a>) -> B,
B: Borrow<V::SelfType<'v>>,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let value = default(&entry.key);
entry.insert(value)
}
}
}
pub fn and_modify<F>(self, f: F) -> Result<Self>
where
F: FnOnce(&mut AccessGuardMut<'_, V>) -> Result<()>,
{
match self {
Entry::Occupied(mut entry) => {
{
let mut guard = entry.get_mut()?;
f(&mut guard)?;
}
Ok(Entry::Occupied(entry))
}
Entry::Vacant(entry) => Ok(Entry::Vacant(entry)),
}
}
}
pub struct OccupiedEntry<'a, K: Key + 'static, V: Value + 'static> {
tree: &'a mut BtreeMut<K, V>,
key: K::SelfType<'a>,
}
impl<'a, K: Key + 'static, V: Value + 'static> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K::SelfType<'a> {
&self.key
}
pub fn get(&self) -> Result<AccessGuard<'_, V>> {
self.tree.get(&self.key)?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})
}
pub fn get_mut(&mut self) -> Result<AccessGuardMut<'_, V>> {
self.tree.get_mut(&self.key)?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})
}
pub fn into_mut(self) -> Result<AccessGuardMut<'a, V>> {
self.tree.get_mut(&self.key)?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})
}
pub fn insert<'v>(
&mut self,
value: impl Borrow<V::SelfType<'v>>,
) -> Result<AccessGuard<'_, V>> {
let value_len = V::as_bytes(value.borrow()).as_ref().len();
if value_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(value_len));
}
let key_len = K::as_bytes(&self.key).as_ref().len();
if value_len + key_len > MAX_PAIR_LENGTH {
return Err(StorageError::ValueTooLarge(value_len + key_len));
}
self.tree.insert(&self.key, value.borrow())?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})
}
pub fn remove(self) -> Result<AccessGuard<'a, V>> {
self.tree.remove(&self.key)?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})
}
pub fn remove_entry(self) -> Result<(K::SelfType<'a>, AccessGuard<'a, V>)> {
let OccupiedEntry { tree, key } = self;
let value = tree.remove(&key)?.ok_or_else(|| {
StorageError::Corrupted(
"entry for key disappeared while OccupiedEntry was live".to_string(),
)
})?;
Ok((key, value))
}
}
pub struct VacantEntry<'a, K: Key + 'static, V: Value + 'static> {
tree: &'a mut BtreeMut<K, V>,
key: K::SelfType<'a>,
}
impl<'a, K: Key + 'static, V: Value + 'static> VacantEntry<'a, K, V> {
pub fn key(&self) -> &K::SelfType<'a> {
&self.key
}
pub fn into_key(self) -> K::SelfType<'a> {
self.key
}
pub fn insert<'v>(self, value: impl Borrow<V::SelfType<'v>>) -> Result<AccessGuardMut<'a, V>> {
let value_len = V::as_bytes(value.borrow()).as_ref().len();
if value_len > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(value_len));
}
let key_len = K::as_bytes(&self.key).as_ref().len();
if value_len + key_len > MAX_PAIR_LENGTH {
return Err(StorageError::ValueTooLarge(value_len + key_len));
}
self.tree.insert(&self.key, value.borrow())?;
self.tree.get_mut(&self.key)?.ok_or_else(|| {
StorageError::Corrupted(
"inserted entry not found after VacantEntry::insert".to_string(),
)
})
}
}
#[cfg(feature = "experimental-api-5")]
pub(crate) fn bound_to_bytes<'a, K: Key + 'a, KR: Borrow<K::SelfType<'a>>>(
bound: &Bound<KR>,
) -> Bound<Vec<u8>> {
match bound {
Bound::Included(key) => Bound::Included(K::as_bytes(key.borrow()).as_ref().to_vec()),
Bound::Excluded(key) => Bound::Excluded(K::as_bytes(key.borrow()).as_ref().to_vec()),
Bound::Unbounded => Bound::Unbounded,
}
}
#[cfg(feature = "experimental-api-5")]
pub struct Cursor<'a, K: Key + 'static, V: Value + 'static> {
#[cfg_attr(not(feature = "experimental_cursor"), allow(dead_code))]
inner: BtreeCursor<K, V>,
_transaction_guard: Arc<TransactionGuard>,
_lifetime: PhantomData<&'a ()>,
}
#[cfg(feature = "experimental-api-5")]
impl<K: Key + 'static, V: Value + 'static> Cursor<'_, K, V> {
pub(crate) fn new(inner: BtreeCursor<K, V>, guard: Arc<TransactionGuard>) -> Self {
Self {
inner,
_transaction_guard: guard,
_lifetime: PhantomData,
}
}
}
#[cfg(feature = "experimental_cursor")]
impl<'a, K: Key + 'static, V: Value + 'static> Cursor<'a, K, V> {
#[allow(clippy::type_complexity)]
pub fn peek_next(&mut self) -> Result<Option<(AccessGuard<'a, K>, AccessGuard<'a, V>)>> {
self.inner.peek_next()
}
#[allow(clippy::type_complexity)]
pub fn peek_prev(&mut self) -> Result<Option<(AccessGuard<'a, K>, AccessGuard<'a, V>)>> {
self.inner.peek_prev()
}
#[allow(clippy::should_implement_trait, clippy::type_complexity)]
pub fn next(&mut self) -> Result<Option<(AccessGuard<'a, K>, AccessGuard<'a, V>)>> {
self.inner.next()
}
#[allow(clippy::type_complexity)]
pub fn prev(&mut self) -> Result<Option<(AccessGuard<'a, K>, AccessGuard<'a, V>)>> {
self.inner.prev()
}
}
#[cfg(feature = "experimental_cursor")]
pub struct CursorMut<'a, K: Key + 'static, V: Value + 'static> {
inner: BtreeCursorMut<'a, K, V>,
transaction: &'a WriteTransaction,
errored: bool,
closed: bool,
}
#[cfg(feature = "experimental_cursor")]
impl<'a, K: Key + 'static, V: Value + 'static> CursorMut<'a, K, V> {
pub(crate) fn new(inner: BtreeCursorMut<'a, K, V>, transaction: &'a WriteTransaction) -> Self {
Self {
inner,
transaction,
errored: false,
closed: false,
}
}
#[allow(clippy::type_complexity)]
pub fn peek_next(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
match self.inner.peek_next() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
#[allow(clippy::type_complexity)]
pub fn peek_prev(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
match self.inner.peek_prev() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
#[allow(clippy::should_implement_trait, clippy::type_complexity)]
pub fn next(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
if let Err(err) = self.inner.apply_pending_inserts() {
return Err(self.latch_error(err));
}
match self.inner.next() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
#[allow(clippy::type_complexity)]
pub fn prev(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
if let Err(err) = self.inner.apply_pending_inserts() {
return Err(self.latch_error(err));
}
match self.inner.prev() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
pub fn insert_before<'k, 'v>(
&mut self,
key: impl Borrow<K::SelfType<'k>>,
value: impl Borrow<V::SelfType<'v>>,
) -> Result<()> {
self.check_usable()?;
let key_bytes = K::as_bytes(key.borrow());
let value_bytes = V::as_bytes(value.borrow());
Self::check_lengths(key_bytes.as_ref(), value_bytes.as_ref())?;
match self
.inner
.insert_before(key_bytes.as_ref(), value_bytes.as_ref())
{
Ok(true) => Ok(()),
Ok(false) => Err(StorageError::UnorderedKey),
Err(err) => Err(self.latch_error(err)),
}
}
pub fn insert_after<'k, 'v>(
&mut self,
key: impl Borrow<K::SelfType<'k>>,
value: impl Borrow<V::SelfType<'v>>,
) -> Result<()> {
self.check_usable()?;
let key_bytes = K::as_bytes(key.borrow());
let value_bytes = V::as_bytes(value.borrow());
Self::check_lengths(key_bytes.as_ref(), value_bytes.as_ref())?;
match self
.inner
.insert_after(key_bytes.as_ref(), value_bytes.as_ref())
{
Ok(true) => Ok(()),
Ok(false) => Err(StorageError::UnorderedKey),
Err(err) => Err(self.latch_error(err)),
}
}
#[allow(clippy::type_complexity)]
pub fn remove_next(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
if let Err(err) = self.inner.apply_pending_inserts() {
return Err(self.latch_error(err));
}
match self.inner.remove_next() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
#[allow(clippy::type_complexity)]
pub fn remove_prev(&mut self) -> Result<Option<(AccessGuard<'_, K>, AccessGuard<'_, V>)>> {
self.check_usable()?;
if let Err(err) = self.inner.apply_pending_inserts() {
return Err(self.latch_error(err));
}
match self.inner.remove_prev() {
Ok(entry) => Ok(entry),
Err(err) => {
self.errored = true;
Err(err)
}
}
}
fn check_lengths(key: &[u8], value: &[u8]) -> Result {
if value.len() > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(value.len()));
}
if key.len() > MAX_VALUE_LENGTH {
return Err(StorageError::ValueTooLarge(key.len()));
}
if value.len() + key.len() > MAX_PAIR_LENGTH {
return Err(StorageError::ValueTooLarge(value.len() + key.len()));
}
Ok(())
}
pub fn close(mut self) -> Result {
self.closed = true;
self.finish()
}
fn check_usable(&self) -> Result {
if self.errored {
return Err(StorageError::PreviousIo);
}
Ok(())
}
fn latch_error(&mut self, err: StorageError) -> StorageError {
self.errored = true;
if self.inner.poisoned() {
self.transaction.poison();
}
err
}
fn finish(&mut self) -> Result {
let result = self.inner.finish();
if result.is_err() || self.inner.poisoned() {
self.transaction.poison();
}
result
}
}
#[cfg(feature = "experimental_cursor")]
impl<K: Key + 'static, V: Value + 'static> Drop for CursorMut<'_, K, V> {
fn drop(&mut self) {
if self.closed {
return;
}
let _ = self.finish();
}
}