uqa_storage/mvcc/commit/
cursor.rs1use std::ops::Bound;
10use std::sync::Arc;
11
12use crate::mvcc::overlay::run::{RunCursor, RunEntry, SpilledRun};
13use crate::mvcc::VersionResult;
14use crate::read_control::StorageReadControl;
15
16use super::metadata::PreparedWriteMetadata;
17use super::PreparedRecordWrite;
18
19enum Source<'a> {
20 Resident(std::slice::Iter<'a, PreparedRecordWrite>),
21 Spilled(RunCursor),
22}
23
24pub struct PreparedWriteCursor<'a> {
26 source: Source<'a>,
27}
28
29impl<'a> PreparedWriteCursor<'a> {
30 pub(super) fn resident(writes: &'a [PreparedRecordWrite]) -> Self {
31 Self {
32 source: Source::Resident(writes.iter()),
33 }
34 }
35
36 pub(super) fn spilled(run: &Arc<SpilledRun>) -> Self {
37 Self {
38 source: Source::Spilled(run.cursor(Bound::Unbounded)),
39 }
40 }
41
42 pub(super) fn spilled_from(run: &Arc<SpilledRun>, start: &[u8]) -> Self {
43 Self {
44 source: Source::Spilled(run.cursor(Bound::Included(start))),
45 }
46 }
47
48 pub fn next(
50 &mut self,
51 control: &StorageReadControl,
52 ) -> VersionResult<Option<PreparedRecordWrite>> {
53 match &mut self.source {
54 Source::Resident(writes) => {
55 control.cancellation().check()?;
56 Ok(writes.next().cloned())
57 }
58 Source::Spilled(cursor) => {
59 let Some(entry) = cursor.next(control)? else {
60 return Ok(None);
61 };
62 spilled_write(cursor.run(), entry, control).map(Some)
63 }
64 }
65 }
66
67 pub fn next_metadata(
69 &mut self,
70 control: &StorageReadControl,
71 ) -> VersionResult<Option<PreparedWriteMetadata>> {
72 match &mut self.source {
73 Source::Resident(writes) => {
74 control.cancellation().check()?;
75 Ok(writes.next().map(|write| {
76 PreparedWriteMetadata::new(
77 write.shared_key(),
78 write.expected(),
79 write.kind(),
80 write.value().map(|value| value.len() as u64),
81 )
82 }))
83 }
84 Source::Spilled(cursor) => Ok(cursor.next(control)?.map(|entry| {
85 let value_len = entry.value.map(|location| location.len);
86 PreparedWriteMetadata::new(entry.key, entry.expected, entry.kind, value_len)
87 })),
88 }
89 }
90}
91
92fn spilled_write(
93 run: &SpilledRun,
94 entry: RunEntry,
95 control: &StorageReadControl,
96) -> VersionResult<PreparedRecordWrite> {
97 let value = entry
98 .value
99 .map(|location| run.load_value(location, control))
100 .transpose()?;
101 Ok(PreparedRecordWrite::from_shared(entry.key, entry.expected, value).with_kind(entry.kind))
102}