Skip to main content

marsdb_storage/
txn.rs

1use std::borrow::Borrow;
2
3use redb::{
4    AccessGuard, Key, MultimapRange, MultimapTable, MultimapTableDefinition, MultimapValue, Range,
5    ReadOnlyMultimapTable, ReadOnlyTable, ReadTransaction, ReadableMultimapTable, ReadableTable,
6    Table, TableDefinition, Value, WriteTransaction,
7};
8
9use crate::error::StorageError;
10
11/// Either kind of redb transaction — lets a function that only ever reads
12/// (`.get()`/`.iter()`, never `.insert()`/`.remove()`) run against a real
13/// `WriteTransaction` (the crash-safety boundary for a write statement) or
14/// a `ReadTransaction` (so a read-only statement doesn't have to contend
15/// for redb's single-writer lock at all). `WriteTransaction`/
16/// `ReadTransaction` share no common trait in redb itself — `open_table`/
17/// `open_multimap_table` are inherent methods on two unrelated structs,
18/// returning different concrete types (`Table`/`ReadOnlyTable`,
19/// `MultimapTable`/`ReadOnlyMultimapTable`) — so this (and `TableHandle`/
20/// `MultimapTableHandle` below) is a small local abstraction over that,
21/// not something redb provides.
22#[derive(Clone, Copy)]
23pub enum Txn<'a> {
24    Write(&'a WriteTransaction),
25    Read(&'a ReadTransaction),
26}
27
28impl<'a> Txn<'a> {
29    pub fn open_table<K: Key + 'static, V: Value + 'static>(
30        &self,
31        def: TableDefinition<K, V>,
32    ) -> Result<TableHandle<'a, K, V>, StorageError> {
33        Ok(match self {
34            Txn::Write(w) => TableHandle::Write(w.open_table(def)?),
35            Txn::Read(r) => TableHandle::Read(r.open_table(def)?),
36        })
37    }
38
39    pub fn open_multimap_table<K: Key + 'static, V: Key + 'static>(
40        &self,
41        def: MultimapTableDefinition<K, V>,
42    ) -> Result<MultimapTableHandle<'a, K, V>, StorageError> {
43        Ok(match self {
44            Txn::Write(w) => MultimapTableHandle::Write(w.open_multimap_table(def)?),
45            Txn::Read(r) => MultimapTableHandle::Read(r.open_multimap_table(def)?),
46        })
47    }
48}
49
50/// Deliberately exposes only `get`/`iter` as plain inherent methods, not a
51/// full `redb::ReadableTable` trait impl — every read-only call site in
52/// this codebase today only ever calls those two (no `.range()`/
53/// `.first()`/`.last()` anywhere), so matching the full trait (including
54/// its lifetime-heavy generic `range`) would be boilerplate for methods
55/// nothing calls.
56pub enum TableHandle<'a, K: Key + 'static, V: Value + 'static> {
57    Write(Table<'a, K, V>),
58    Read(ReadOnlyTable<K, V>),
59}
60
61impl<'a, K: Key + 'static, V: Value + 'static> TableHandle<'a, K, V> {
62    pub fn get<'k>(
63        &self,
64        key: impl Borrow<K::SelfType<'k>>,
65    ) -> Result<Option<AccessGuard<'_, V>>, StorageError> {
66        Ok(match self {
67            TableHandle::Write(t) => t.get(key)?,
68            TableHandle::Read(t) => t.get(key)?,
69        })
70    }
71
72    pub fn iter(&self) -> Result<Range<'_, K, V>, StorageError> {
73        Ok(match self {
74            TableHandle::Write(t) => t.iter()?,
75            TableHandle::Read(t) => t.iter()?,
76        })
77    }
78}
79
80pub enum MultimapTableHandle<'a, K: Key + 'static, V: Key + 'static> {
81    Write(MultimapTable<'a, K, V>),
82    Read(ReadOnlyMultimapTable<K, V>),
83}
84
85impl<'a, K: Key + 'static, V: Key + 'static> MultimapTableHandle<'a, K, V> {
86    pub fn get<'k>(
87        &self,
88        key: impl Borrow<K::SelfType<'k>>,
89    ) -> Result<MultimapValue<'_, V>, StorageError> {
90        Ok(match self {
91            MultimapTableHandle::Write(t) => t.get(key)?,
92            MultimapTableHandle::Read(t) => t.get(key)?,
93        })
94    }
95
96    #[allow(dead_code)] // not called by any current read path, kept for parity with TableHandle::iter
97    pub fn iter(&self) -> Result<MultimapRange<'_, K, V>, StorageError> {
98        Ok(match self {
99            MultimapTableHandle::Write(t) => t.iter()?,
100            MultimapTableHandle::Read(t) => t.iter()?,
101        })
102    }
103}