1use std::sync::Arc;
10
11use uqa_core::memory::BudgetedVec;
12
13use crate::mvcc::{CommitSequence, DatabaseId, PrivateRecordRevision};
14use crate::read_control::{
15 KeyReadVisitor, KeyValueReadVisitor, StorageReadControl, ValueReadVisitor,
16};
17use crate::{KeyValueBatch, StorageBackendResult};
18
19mod snapshot;
20
21pub(crate) fn for_each_key(
23 read: &dyn KeyValueRead,
24 prefix: &[u8],
25 visit: &mut dyn FnMut(&[u8]) -> StorageBackendResult<bool>,
26) -> StorageBackendResult<()> {
27 let mut after = None::<BudgetedVec<u8>>;
28 loop {
29 let mut keys = BudgetedVec::new(read.control().memory());
30 read.visit_keys_after(prefix, after.as_deref(), 128, read.control(), &mut |key| {
31 let mut owned = BudgetedVec::new(read.control().memory());
32 owned.extend_from_slice(key)?;
33 keys.push(owned)?;
34 Ok(())
35 })?;
36 let Some(last) = keys.last() else {
37 return Ok(());
38 };
39 let mut next = BudgetedVec::new(read.control().memory());
40 next.extend_from_slice(last)?;
41 after = Some(next);
42 for key in keys.iter() {
43 read.control().check()?;
44 if !visit(key)? {
45 return Ok(());
46 }
47 }
48 }
49}
50
51pub type KeyValueReadScope<'a> = dyn FnMut(&dyn KeyValueRead) -> StorageBackendResult<()> + 'a;
52pub type KeyValueReadKeyIterator<'a> =
53 dyn Iterator<Item = StorageBackendResult<BudgetedVec<u8>>> + 'a;
54pub type KeyValuePointVisitor<'a> =
55 dyn FnMut(&[u8], Option<&[u8]>) -> StorageBackendResult<bool> + 'a;
56pub type KeyPresenceVisitor<'a> = dyn FnMut(&[u8], bool) -> StorageBackendResult<bool> + 'a;
57pub type KeyValueMutation<'a> =
58 dyn FnMut(&dyn KeyValueRead, &mut dyn KeyValueBatch) -> StorageBackendResult<()> + 'a;
59pub type KeyValueVersionedMutation<'a> = dyn FnMut(
60 crate::mvcc::StorageMutationOrigin,
61 &dyn KeyValueRead,
62 &mut dyn KeyValueBatch,
63 ) -> StorageBackendResult<()>
64 + 'a;
65
66pub trait KeyValueRead {
68 fn control(&self) -> &StorageReadControl;
69 fn revision(&self, prefixes: &[&[u8]]) -> StorageBackendResult<KeyValueReadRevision>;
70 fn marker_fingerprint(&self, _key: &[u8]) -> StorageBackendResult<Option<[u8; 32]>> {
72 self.control().check()?;
73 Ok(None)
74 }
75 fn record_revision(&self, _key: &[u8]) -> StorageBackendResult<Option<KeyValueReadRevision>> {
77 self.control().check()?;
78 Err(super::codec::other_error(
79 "individual record revisions are not supported",
80 ))
81 }
82 fn retained_source(
84 &self,
85 _key: &[u8],
86 ) -> StorageBackendResult<Option<Arc<dyn KeyValueRead + Send + Sync>>> {
87 self.control().check()?;
88 Ok(None)
89 }
90 fn retain(
92 &self,
93 prefixes: &[&[u8]],
94 ) -> StorageBackendResult<Arc<dyn KeyValueRead + Send + Sync>> {
95 snapshot::capture(self, prefixes)
96 }
97 fn visit_value(&self, key: &[u8], visit: &mut ValueReadVisitor<'_>)
98 -> StorageBackendResult<()>;
99 fn visit_prefix(
100 &self,
101 prefix: &[u8],
102 visit: &mut KeyValueReadVisitor<'_>,
103 ) -> StorageBackendResult<()>;
104
105 fn visit_values(
107 &self,
108 keys: &mut KeyValueReadKeyIterator<'_>,
109 visit: &mut KeyValuePointVisitor<'_>,
110 ) -> StorageBackendResult<()> {
111 loop {
112 self.control().check()?;
113 let Some(key) = keys.next() else {
114 return Ok(());
115 };
116 let key = key?;
117 let mut more = true;
118 self.visit_value(&key, &mut |value| {
119 more = visit(&key, value)?;
120 Ok(())
121 })?;
122 self.control().check()?;
123 if !more {
124 return Ok(());
125 }
126 }
127 }
128
129 fn visit_key_presence(
131 &self,
132 keys: &mut KeyValueReadKeyIterator<'_>,
133 visit: &mut KeyPresenceVisitor<'_>,
134 ) -> StorageBackendResult<()> {
135 loop {
136 self.control().check()?;
137 let Some(key) = keys.next() else {
138 return Ok(());
139 };
140 let key = key?;
141 let mut present = false;
142 self.visit_keys_after(&key, None, 1, self.control(), &mut |found| {
143 present = found == &*key;
144 Ok(())
145 })?;
146 self.control().check()?;
147 let more = visit(&key, present)?;
148 self.control().check()?;
149 if !more {
150 return Ok(());
151 }
152 }
153 }
154
155 fn visit_value_budgeted(
157 &self,
158 _key: &[u8],
159 control: &StorageReadControl,
160 _visit: &mut ValueReadVisitor<'_>,
161 ) -> StorageBackendResult<()> {
162 control.check()?;
163 Err(super::codec::other_error(
164 "controlled compound value reads are not supported",
165 ))
166 }
167
168 fn visit_value_bounded(
170 &self,
171 _key: &[u8],
172 _max_bytes: usize,
173 control: &StorageReadControl,
174 _visit: &mut ValueReadVisitor<'_>,
175 ) -> StorageBackendResult<()> {
176 control.check()?;
177 Err(super::codec::other_error(
178 "size-bounded compound value reads are not supported",
179 ))
180 }
181
182 fn visit_prefix_after(
184 &self,
185 _prefix: &[u8],
186 _after: Option<&[u8]>,
187 _limit: usize,
188 control: &StorageReadControl,
189 _visit: &mut KeyValueReadVisitor<'_>,
190 ) -> StorageBackendResult<()> {
191 control.check()?;
192 Err(super::codec::other_error(
193 "controlled compound prefix reads are not supported",
194 ))
195 }
196
197 fn visit_keys_after(
199 &self,
200 _prefix: &[u8],
201 _after: Option<&[u8]>,
202 _limit: usize,
203 control: &StorageReadControl,
204 _visit: &mut KeyReadVisitor<'_>,
205 ) -> StorageBackendResult<()> {
206 control.check()?;
207 Err(super::codec::other_error(
208 "compound key-only scans are not supported",
209 ))
210 }
211
212 fn contains_prefix_budgeted(
214 &self,
215 _prefix: &[u8],
216 control: &StorageReadControl,
217 ) -> StorageBackendResult<bool> {
218 control.check()?;
219 Err(super::codec::other_error(
220 "compound key-only probes are not supported",
221 ))
222 }
223
224 fn get(&self, key: &[u8]) -> StorageBackendResult<Option<BudgetedVec<u8>>> {
225 let mut result = None;
226 self.visit_value(key, &mut |value| {
227 if let Some(value) = value {
228 let mut bytes = BudgetedVec::new(self.control().memory());
229 bytes.extend_from_slice(value)?;
230 result = Some(bytes);
231 }
232 Ok(())
233 })?;
234 Ok(result)
235 }
236}
237
238#[cfg(test)]
239mod tests;
240
241#[derive(Clone)]
243pub struct KeyValueReadRevision(Revision);
244
245#[derive(Clone)]
246enum Revision {
247 Memory(Arc<()>),
248 Record(crate::mvcc::VisibleRecordRevision),
249 Records {
250 database: DatabaseId,
251 committed: CommitSequence,
252 private: Option<PrivateRecordRevision>,
253 },
254}
255
256impl KeyValueReadRevision {
257 pub(crate) fn observed_commit(&self, database: DatabaseId) -> Option<CommitSequence> {
258 match &self.0 {
259 Revision::Record(revision) => revision.committed(database),
260 _ => None,
261 }
262 }
263
264 pub fn same_private_changes(&self, other: &Self) -> bool {
266 matches!((&self.0, &other.0), (
267 Revision::Records { database: a, private: ap, .. },
268 Revision::Records { database: b, private: bp, .. }
269 ) if a == b && ap == bp)
270 }
271
272 pub fn follows_by_one_commit(&self, earlier: &Self) -> bool {
274 match (earlier.committed_state(), self.committed_state()) {
275 (Some((database, before, _)), Some((current, after, false))) => {
276 database == current && before.successor().ok() == Some(after)
277 }
278 _ => false,
279 }
280 }
281
282 pub fn same_committed_state(&self, other: &Self) -> bool {
284 match (self.committed_state(), other.committed_state()) {
285 (Some((database, sequence, _)), Some((other_database, other_sequence, _))) => {
286 database == other_database && sequence == other_sequence
287 }
288 _ => false,
289 }
290 }
291
292 fn committed_state(&self) -> Option<(DatabaseId, CommitSequence, bool)> {
294 match &self.0 {
295 Revision::Record(record) => record
296 .committed_sequence()
297 .map(|sequence| (record.database(), sequence, record.is_private())),
298 Revision::Records {
299 database,
300 committed,
301 private,
302 } => Some((*database, *committed, private.is_some())),
303 Revision::Memory(_) => None,
304 }
305 }
306
307 pub(crate) fn record_database(&self) -> Option<DatabaseId> {
308 match &self.0 {
309 Revision::Record(revision) => Some(revision.database()),
310 Revision::Memory(_) | Revision::Records { .. } => None,
311 }
312 }
313
314 pub fn has_private_changes(&self) -> bool {
316 match &self.0 {
317 Revision::Memory(_) => true,
318 Revision::Record(revision) => revision.is_private(),
319 Revision::Records { private, .. } => private.is_some(),
320 }
321 }
322
323 pub fn fresh() -> Self {
325 Self(Revision::Memory(Arc::new(())))
326 }
327
328 pub(crate) fn memory(identity: &Arc<()>) -> Self {
329 Self(Revision::Memory(Arc::clone(identity)))
330 }
331
332 pub(crate) fn record(revision: crate::mvcc::VisibleRecordRevision) -> Self {
333 Self(Revision::Record(revision))
334 }
335
336 pub(crate) fn records(
337 database: DatabaseId,
338 committed: CommitSequence,
339 private: Option<PrivateRecordRevision>,
340 ) -> Self {
341 Self(Revision::Records {
342 database,
343 committed,
344 private,
345 })
346 }
347}
348
349impl PartialEq for KeyValueReadRevision {
350 fn eq(&self, other: &Self) -> bool {
351 match (&self.0, &other.0) {
352 (Revision::Memory(a), Revision::Memory(b)) => Arc::ptr_eq(a, b),
353 (Revision::Record(a), Revision::Record(b)) => a == b,
354 (
355 Revision::Records {
356 database: a,
357 committed: ac,
358 private: ap,
359 },
360 Revision::Records {
361 database: b,
362 committed: bc,
363 private: bp,
364 },
365 ) => a == b && ac == bc && ap == bp,
366 _ => false,
367 }
368 }
369}
370impl Eq for KeyValueReadRevision {}