1use crate::key_value::{KeyValueRead, KeyValueReadRevision};
8use crate::mvcc::{DatabaseId, VersionError};
9use crate::mvcc::{MergedRecordSnapshot, VersionResult};
10use crate::read_control::{KeyReadVisitor, KeyValueReadVisitor, StorageReadControl};
11use crate::{read_control::ValueReadVisitor, StorageBackendResult};
12use uqa_core::memory::BudgetedVec;
13
14pub struct RecordRead<'a> {
16 pub(super) view: &'a MergedRecordSnapshot,
17 pub(super) database: DatabaseId,
18 pub(super) control: &'a StorageReadControl,
19}
20
21impl<'a> RecordRead<'a> {
22 pub fn new(
23 view: &'a MergedRecordSnapshot,
24 database: DatabaseId,
25 control: &'a StorageReadControl,
26 ) -> Self {
27 Self {
28 view,
29 database,
30 control,
31 }
32 }
33}
34
35impl KeyValueRead for RecordRead<'_> {
36 fn control(&self) -> &StorageReadControl {
37 self.control
38 }
39
40 fn marker_fingerprint(&self, key: &[u8]) -> StorageBackendResult<Option<[u8; 32]>> {
41 self.view
42 .marker_fingerprint(self.database, key, self.control)
43 .map(Some)
44 }
45
46 fn revision(&self, prefixes: &[&[u8]]) -> StorageBackendResult<KeyValueReadRevision> {
47 self.control.check()?;
48 let mut private = None;
49 for prefix in prefixes {
50 let mut after = BudgetedVec::new(self.control.memory());
51 loop {
52 let page = self
53 .view
54 .private_keys(
55 prefix,
56 (!after.is_empty()).then_some(&*after),
57 64,
58 self.control,
59 )
60 .map_err(VersionError::into_storage_error)?;
61 let Some(last) = page.last() else { break };
62 after.clear();
63 after.extend_from_slice(last.key())?;
64 for record in page.iter() {
65 private = private.max(Some(record.revision()));
66 }
67 }
68 }
69 Ok(KeyValueReadRevision::records(
70 self.database,
71 self.view.sequence(),
72 private,
73 ))
74 }
75
76 fn record_revision(&self, key: &[u8]) -> StorageBackendResult<Option<KeyValueReadRevision>> {
77 self.view
78 .record_revision(self.database, key, self.control)
79 .map(|revision| revision.map(KeyValueReadRevision::record))
80 .map_err(VersionError::into_storage_error)
81 }
82
83 fn retained_source(
84 &self,
85 key: &[u8],
86 ) -> StorageBackendResult<Option<std::sync::Arc<dyn KeyValueRead + Send + Sync>>> {
87 self.view
88 .retained_source(key, self.control)
89 .map_err(VersionError::into_storage_error)
90 }
91
92 fn retain(
93 &self,
94 _prefixes: &[&[u8]],
95 ) -> StorageBackendResult<std::sync::Arc<dyn KeyValueRead + Send + Sync>> {
96 self.control.check()?;
97 let memory = self
98 .control
99 .memory()
100 .reserve(std::mem::size_of::<RetainedRecordRead>())?;
101 Ok(std::sync::Arc::new(RetainedRecordRead {
102 view: self
103 .view
104 .try_clone()
105 .map_err(VersionError::into_storage_error)?,
106 database: self.database,
107 control: self.control.clone(),
108 _memory: memory,
109 }))
110 }
111
112 fn visit_value(
113 &self,
114 key: &[u8],
115 visit: &mut ValueReadVisitor<'_>,
116 ) -> StorageBackendResult<()> {
117 self.visit_value_budgeted(key, self.control, visit)
118 }
119
120 fn visit_prefix(
121 &self,
122 prefix: &[u8],
123 visit: &mut KeyValueReadVisitor<'_>,
124 ) -> StorageBackendResult<()> {
125 self.visit_prefix_after(prefix, None, usize::MAX, self.control, visit)
126 }
127
128 fn visit_value_budgeted(
129 &self,
130 key: &[u8],
131 control: &StorageReadControl,
132 visit: &mut ValueReadVisitor<'_>,
133 ) -> StorageBackendResult<()> {
134 self.view
135 .visit_value(key, control, &mut |record| {
136 visit(record.and_then(|record| record.value)).map_err(Into::into)
137 })
138 .map_err(VersionError::into_storage_error)
139 }
140
141 fn visit_value_bounded(
142 &self,
143 key: &[u8],
144 max_bytes: usize,
145 control: &StorageReadControl,
146 visit: &mut ValueReadVisitor<'_>,
147 ) -> StorageBackendResult<()> {
148 self.view
149 .visit_value_bounded(key, max_bytes, control, &mut |record| {
150 visit(record.and_then(|record| record.value)).map_err(Into::into)
151 })
152 .map_err(VersionError::into_storage_error)
153 }
154
155 fn visit_prefix_after(
156 &self,
157 prefix: &[u8],
158 after: Option<&[u8]>,
159 limit: usize,
160 control: &StorageReadControl,
161 visit: &mut KeyValueReadVisitor<'_>,
162 ) -> StorageBackendResult<()> {
163 visit_live(self.view, prefix, after, limit, control, visit)
164 .map_err(VersionError::into_storage_error)
165 }
166
167 fn visit_keys_after(
168 &self,
169 prefix: &[u8],
170 after: Option<&[u8]>,
171 limit: usize,
172 control: &StorageReadControl,
173 visit: &mut KeyReadVisitor<'_>,
174 ) -> StorageBackendResult<()> {
175 control.check()?;
176 if limit == 0 {
177 return Ok(());
178 }
179 let mut count = 0;
180 self.view
181 .visit_keys(prefix, after, usize::MAX, control, &mut |key, record| {
182 if record.live {
183 visit(key)?;
184 count += 1;
185 }
186 Ok(count < limit)
187 })
188 .map_err(VersionError::into_storage_error)
189 }
190
191 fn contains_prefix_budgeted(
192 &self,
193 prefix: &[u8],
194 control: &StorageReadControl,
195 ) -> StorageBackendResult<bool> {
196 control.check()?;
197 let mut found = false;
198 self.view
199 .visit_keys(prefix, None, usize::MAX, control, &mut |_, record| {
200 found = record.live;
201 Ok(!found)
202 })
203 .map_err(VersionError::into_storage_error)?;
204 Ok(found)
205 }
206}
207
208pub(super) fn visit_live(
209 view: &MergedRecordSnapshot,
210 prefix: &[u8],
211 after: Option<&[u8]>,
212 limit: usize,
213 control: &StorageReadControl,
214 visit: &mut KeyValueReadVisitor<'_>,
215) -> VersionResult<()> {
216 control.cancellation().check()?;
217 if limit == 0 {
218 return Ok(());
219 }
220 let mut count = 0;
221 view.visit_prefix(prefix, after, usize::MAX, control, &mut |key, record| {
222 if let Some(value) = record.value {
223 visit(key, value)?;
224 count += 1;
225 }
226 Ok(count < limit)
227 })
228}
229
230struct RetainedRecordRead {
231 view: MergedRecordSnapshot,
232 database: DatabaseId,
233 control: StorageReadControl,
234 _memory: uqa_core::memory::MemoryReservation,
235}
236impl RetainedRecordRead {
237 fn read(&self) -> RecordRead<'_> {
238 RecordRead {
239 view: &self.view,
240 database: self.database,
241 control: &self.control,
242 }
243 }
244}
245impl KeyValueRead for RetainedRecordRead {
246 fn control(&self) -> &StorageReadControl {
247 &self.control
248 }
249 fn marker_fingerprint(&self, key: &[u8]) -> StorageBackendResult<Option<[u8; 32]>> {
250 self.read().marker_fingerprint(key)
251 }
252 fn revision(&self, prefixes: &[&[u8]]) -> StorageBackendResult<KeyValueReadRevision> {
253 self.read().revision(prefixes)
254 }
255 fn record_revision(&self, key: &[u8]) -> StorageBackendResult<Option<KeyValueReadRevision>> {
256 self.read().record_revision(key)
257 }
258 fn retained_source(
259 &self,
260 key: &[u8],
261 ) -> StorageBackendResult<Option<std::sync::Arc<dyn KeyValueRead + Send + Sync>>> {
262 self.read().retained_source(key)
263 }
264 fn retain(
265 &self,
266 prefixes: &[&[u8]],
267 ) -> StorageBackendResult<std::sync::Arc<dyn KeyValueRead + Send + Sync>> {
268 self.read().retain(prefixes)
269 }
270 fn visit_value(
271 &self,
272 key: &[u8],
273 visit: &mut ValueReadVisitor<'_>,
274 ) -> StorageBackendResult<()> {
275 self.read().visit_value(key, visit)
276 }
277 fn visit_prefix(
278 &self,
279 prefix: &[u8],
280 visit: &mut KeyValueReadVisitor<'_>,
281 ) -> StorageBackendResult<()> {
282 self.read().visit_prefix(prefix, visit)
283 }
284 fn visit_value_budgeted(
285 &self,
286 key: &[u8],
287 control: &StorageReadControl,
288 visit: &mut ValueReadVisitor<'_>,
289 ) -> StorageBackendResult<()> {
290 self.read().visit_value_budgeted(key, control, visit)
291 }
292 fn visit_value_bounded(
293 &self,
294 key: &[u8],
295 max_bytes: usize,
296 control: &StorageReadControl,
297 visit: &mut ValueReadVisitor<'_>,
298 ) -> StorageBackendResult<()> {
299 self.read()
300 .visit_value_bounded(key, max_bytes, control, visit)
301 }
302 fn visit_prefix_after(
303 &self,
304 prefix: &[u8],
305 after: Option<&[u8]>,
306 limit: usize,
307 control: &StorageReadControl,
308 visit: &mut KeyValueReadVisitor<'_>,
309 ) -> StorageBackendResult<()> {
310 self.read()
311 .visit_prefix_after(prefix, after, limit, control, visit)
312 }
313 fn contains_prefix_budgeted(
314 &self,
315 prefix: &[u8],
316 control: &StorageReadControl,
317 ) -> StorageBackendResult<bool> {
318 self.read().contains_prefix_budgeted(prefix, control)
319 }
320
321 fn visit_keys_after(
322 &self,
323 prefix: &[u8],
324 after: Option<&[u8]>,
325 limit: usize,
326 control: &StorageReadControl,
327 visit: &mut KeyReadVisitor<'_>,
328 ) -> StorageBackendResult<()> {
329 self.read()
330 .visit_keys_after(prefix, after, limit, control, visit)
331 }
332}