uqa_storage/mvcc/serializable/
coordinator.rs1mod local;
10
11use std::sync::Arc;
12
13use super::{SerializableGraph, SerializableParticipant, SerializableTransactionId};
14use crate::{
15 mvcc::{CommittedRecordSnapshot, VersionError, VersionResult, VersionedPersistence},
16 read_control::StorageReadControl,
17};
18
19pub use local::LocalSerializableState;
20
21pub trait SerializableLeases {
23 fn retain(
24 &self,
25 id: SerializableTransactionId,
26 control: &StorageReadControl,
27 ) -> VersionResult<SerializableParticipant>;
28
29 fn is_alive(
30 &self,
31 id: SerializableTransactionId,
32 control: &StorageReadControl,
33 ) -> VersionResult<bool>;
34
35 fn reclaim(&self);
36}
37
38pub type SerializableOperation<'a> =
39 dyn FnMut(&mut SerializableGraph, &dyn SerializableLeases) -> VersionResult<()> + 'a;
40
41pub trait SerializableCoordinator: VersionedPersistence {
43 fn with_serializable_admission(
45 &self,
46 control: &StorageReadControl,
47 operation: &mut SerializableOperation<'_>,
48 ) -> VersionResult<()>;
49
50 fn admit_serializable_snapshot(
52 &self,
53 read_only: bool,
54 control: &StorageReadControl,
55 ) -> VersionResult<(SerializableParticipant, Arc<dyn CommittedRecordSnapshot>)> {
56 admit_serializable(self, read_only, control, || self.snapshot(control))
57 }
58
59 fn recover_serializable_participants(&self, control: &StorageReadControl) -> VersionResult<()> {
61 self.with_serializable_admission(control, &mut |graph, leases| {
62 recover(self, graph, leases, control)
63 })
64 }
65}
66
67pub fn admit_serializable<C: SerializableCoordinator + ?Sized, T>(
69 coordinator: &C,
70 read_only: bool,
71 control: &StorageReadControl,
72 capture: impl FnOnce() -> VersionResult<T>,
73) -> VersionResult<(SerializableParticipant, T)> {
74 let mut capture = Some(capture);
75 let mut result = None;
76 coordinator.with_serializable_admission(control, &mut |graph, leases| {
77 let capture = capture.take().ok_or(VersionError::InvalidEncoding(
78 "serializable admission operation was replayed",
79 ))?;
80 recover(coordinator, graph, leases, control)?;
81 let participant =
82 graph.admit_with_lease(read_only, control, |id| leases.retain(id, control))?;
83 let view = capture()?;
84 result = Some((participant, view));
85 Ok(())
86 })?;
87 result.ok_or(VersionError::InvalidEncoding(
88 "serializable admission operation was not invoked",
89 ))
90}
91
92pub(crate) fn recover<C: SerializableCoordinator + ?Sized>(
93 coordinator: &C,
94 graph: &mut SerializableGraph,
95 leases: &dyn SerializableLeases,
96 control: &StorageReadControl,
97) -> VersionResult<()> {
98 graph.reconcile_publications(control, |transaction| {
99 coordinator.commit_status(transaction, control)
100 })?;
101 graph.recover_abandoned(
102 control,
103 |id| leases.is_alive(id, control),
104 |transaction| coordinator.abort(transaction, control),
105 )?;
106 graph.reclaim();
107 leases.reclaim();
108 Ok(())
109}