uqa_storage/key_value/
view.rs1use 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 KeyValueMutation<'a> =
53 dyn FnMut(&dyn KeyValueRead, &mut dyn KeyValueBatch) -> StorageBackendResult<()> + 'a;
54
55pub trait KeyValueRead {
57 fn control(&self) -> &StorageReadControl;
58 fn revision(&self, prefixes: &[&[u8]]) -> StorageBackendResult<KeyValueReadRevision>;
59 fn retain(
61 &self,
62 prefixes: &[&[u8]],
63 ) -> StorageBackendResult<Arc<dyn KeyValueRead + Send + Sync>> {
64 snapshot::capture(self, prefixes)
65 }
66 fn visit_value(&self, key: &[u8], visit: &mut ValueReadVisitor<'_>)
67 -> StorageBackendResult<()>;
68 fn visit_prefix(
69 &self,
70 prefix: &[u8],
71 visit: &mut KeyValueReadVisitor<'_>,
72 ) -> StorageBackendResult<()>;
73
74 fn visit_value_budgeted(
76 &self,
77 _key: &[u8],
78 control: &StorageReadControl,
79 _visit: &mut ValueReadVisitor<'_>,
80 ) -> StorageBackendResult<()> {
81 control.check()?;
82 Err(super::codec::other_error(
83 "controlled compound value reads are not supported",
84 ))
85 }
86
87 fn visit_prefix_after(
89 &self,
90 _prefix: &[u8],
91 _after: Option<&[u8]>,
92 _limit: usize,
93 control: &StorageReadControl,
94 _visit: &mut KeyValueReadVisitor<'_>,
95 ) -> StorageBackendResult<()> {
96 control.check()?;
97 Err(super::codec::other_error(
98 "controlled compound prefix reads are not supported",
99 ))
100 }
101
102 fn visit_keys_after(
104 &self,
105 _prefix: &[u8],
106 _after: Option<&[u8]>,
107 _limit: usize,
108 control: &StorageReadControl,
109 _visit: &mut KeyReadVisitor<'_>,
110 ) -> StorageBackendResult<()> {
111 control.check()?;
112 Err(super::codec::other_error(
113 "compound key-only scans are not supported",
114 ))
115 }
116
117 fn contains_prefix_budgeted(
119 &self,
120 _prefix: &[u8],
121 control: &StorageReadControl,
122 ) -> StorageBackendResult<bool> {
123 control.check()?;
124 Err(super::codec::other_error(
125 "compound key-only probes are not supported",
126 ))
127 }
128
129 fn get(&self, key: &[u8]) -> StorageBackendResult<Option<BudgetedVec<u8>>> {
130 let mut result = None;
131 self.visit_value(key, &mut |value| {
132 if let Some(value) = value {
133 let mut bytes = BudgetedVec::new(self.control().memory());
134 bytes.extend_from_slice(value)?;
135 result = Some(bytes);
136 }
137 Ok(())
138 })?;
139 Ok(result)
140 }
141}
142
143#[derive(Clone)]
145pub struct KeyValueReadRevision(Revision);
146
147#[derive(Clone)]
148enum Revision {
149 Memory(Arc<()>),
150 Records {
151 database: DatabaseId,
152 committed: CommitSequence,
153 private: Option<PrivateRecordRevision>,
154 },
155}
156
157impl KeyValueReadRevision {
158 pub fn has_private_changes(&self) -> bool {
160 match &self.0 {
161 Revision::Memory(_) => true,
162 Revision::Records { private, .. } => private.is_some(),
163 }
164 }
165
166 pub fn fresh() -> Self {
168 Self(Revision::Memory(Arc::new(())))
169 }
170
171 pub(crate) fn memory(identity: &Arc<()>) -> Self {
172 Self(Revision::Memory(Arc::clone(identity)))
173 }
174
175 pub(crate) fn records(
176 database: DatabaseId,
177 committed: CommitSequence,
178 private: Option<PrivateRecordRevision>,
179 ) -> Self {
180 Self(Revision::Records {
181 database,
182 committed,
183 private,
184 })
185 }
186}
187
188impl PartialEq for KeyValueReadRevision {
189 fn eq(&self, other: &Self) -> bool {
190 match (&self.0, &other.0) {
191 (Revision::Memory(a), Revision::Memory(b)) => Arc::ptr_eq(a, b),
192 (
193 Revision::Records {
194 database: a,
195 committed: ac,
196 private: ap,
197 },
198 Revision::Records {
199 database: b,
200 committed: bc,
201 private: bp,
202 },
203 ) => a == b && ac == bc && ap == bp,
204 _ => false,
205 }
206 }
207}
208impl Eq for KeyValueReadRevision {}