nimiq_database/mdbx/transaction/
mod.rs1mod proxy;
2mod wrapper;
3
4use std::borrow::Cow;
5
6use libmdbx::{NoWriteMap, WriteFlags};
7pub use libmdbx::{TransactionKind, RO, RW};
8use nimiq_database_value::{AsDatabaseBytes, FromDatabaseBytes, IntoDatabaseValue};
9pub use proxy::*;
10pub use wrapper::*;
11
12use super::{MdbxCursor, MdbxWriteCursor};
13use crate::traits::{DupTable, ReadTransaction, Table, WriteTransaction};
14
15#[derive(Debug)]
17pub struct MdbxTransaction<'db, K: TransactionKind> {
18 txn: libmdbx::Transaction<'db, K, NoWriteMap>,
19}
20
21impl<'db, Kind> MdbxTransaction<'db, Kind>
22where
23 Kind: TransactionKind,
24{
25 pub(crate) fn new(txn: libmdbx::Transaction<'db, Kind, NoWriteMap>) -> Self {
26 MdbxTransaction { txn }
27 }
28
29 pub(super) fn open_table<T: Table>(&self, _table: &T) -> libmdbx::Table<'_> {
30 self.txn.open_table(Some(T::NAME)).unwrap()
31 }
32}
33
34impl<'db, Kind> ReadTransaction<'db> for MdbxTransaction<'db, Kind>
35where
36 Kind: TransactionKind,
37{
38 type Cursor<'txn, T: Table>
39 = MdbxCursor<'txn, Kind, T>
40 where
41 'db: 'txn;
42
43 type DupCursor<'txn, T: DupTable>
44 = MdbxCursor<'txn, Kind, T>
45 where
46 'db: 'txn;
47
48 fn get<T: Table>(&self, table: &T, key: &T::Key) -> Option<T::Value> {
49 let table = self.open_table(table);
50
51 let result: Option<Cow<[u8]>> = self
52 .txn
53 .get(&table, &AsDatabaseBytes::as_key_bytes(key))
54 .unwrap();
55
56 Some(FromDatabaseBytes::from_value_bytes(&result?))
57 }
58
59 fn cursor<'txn, T: Table>(&'txn self, table: &T) -> Self::Cursor<'txn, T> {
60 let table = self.open_table(table);
61
62 MdbxCursor::new(self.txn.cursor(&table).unwrap())
63 }
64
65 fn dup_cursor<'txn, T: DupTable>(&'txn self, table: &T) -> Self::DupCursor<'txn, T> {
66 let table = self.open_table(table);
67
68 MdbxCursor::new(self.txn.cursor(&table).unwrap())
69 }
70}
71
72impl<'db> WriteTransaction<'db> for MdbxTransaction<'db, RW> {
73 type WriteCursor<'txn, T: Table>
74 = MdbxWriteCursor<'txn, T>
75 where
76 'db: 'txn;
77
78 type DupWriteCursor<'txn, T: DupTable>
79 = MdbxWriteCursor<'txn, T>
80 where
81 'db: 'txn;
82
83 fn put_reserve<T: Table>(&mut self, table: &T, key: &T::Key, value: &T::Value)
84 where
85 T::Value: IntoDatabaseValue,
86 {
87 let table = self.open_table(table);
88
89 let key = AsDatabaseBytes::as_key_bytes(key);
90 let value_size = IntoDatabaseValue::database_byte_size(value);
91
92 let bytes: &mut [u8] = self
93 .txn
94 .reserve(&table, key, value_size, WriteFlags::empty())
95 .unwrap();
96
97 IntoDatabaseValue::copy_into_database(value, bytes);
98 }
99
100 fn put<T: Table>(&mut self, table: &T, key: &T::Key, value: &T::Value) {
101 let table = self.open_table(table);
102
103 let key = AsDatabaseBytes::as_key_bytes(key);
104 let value = AsDatabaseBytes::as_value_bytes(value);
105
106 self.txn
107 .put(&table, key, value, WriteFlags::empty())
108 .unwrap();
109 }
110
111 fn append<T: Table>(&mut self, table: &T, key: &T::Key, value: &T::Value) {
112 let table = self.open_table(table);
113
114 let key = AsDatabaseBytes::as_key_bytes(key);
115 let value = AsDatabaseBytes::as_value_bytes(value);
116
117 self.txn
118 .put(&table, key, value, WriteFlags::APPEND)
119 .unwrap();
120 }
121
122 fn remove<T: Table>(&mut self, table: &T, key: &T::Key) {
123 let table = self.open_table(table);
124
125 self.txn
126 .del(&table, AsDatabaseBytes::as_key_bytes(key).as_ref(), None)
127 .unwrap();
128 }
129
130 fn remove_item<T: Table>(&mut self, table: &T, key: &T::Key, value: &T::Value) {
131 let table = self.open_table(table);
132
133 self.txn
134 .del(
135 &table,
136 AsDatabaseBytes::as_key_bytes(key).as_ref(),
137 Some(AsDatabaseBytes::as_value_bytes(value).as_ref()),
138 )
139 .unwrap();
140 }
141
142 fn commit(self) {
143 self.txn.commit().unwrap();
144 }
145
146 fn cursor<'txn, T: Table>(&'txn self, table: &T) -> MdbxWriteCursor<'txn, T> {
147 let table = self.open_table(table);
148
149 MdbxWriteCursor::new(self.txn.cursor(&table).unwrap())
150 }
151
152 fn dup_cursor<'txn, T: DupTable>(&'txn self, table: &T) -> Self::DupWriteCursor<'txn, T> {
153 let table = self.open_table(table);
154
155 MdbxCursor::new(self.txn.cursor(&table).unwrap())
156 }
157
158 fn clear_table<T: Table>(&mut self, table: &T) {
159 let table = self.open_table(table);
160
161 self.txn.clear_table(&table).unwrap();
162 }
163}