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_shared(
25 &self,
26 _id: SerializableTransactionId,
27 _control: &StorageReadControl,
28 ) -> VersionResult<SerializableParticipant> {
29 Err(VersionError::InvalidEncoding(
30 "shared participant transport is unavailable",
31 ))
32 }
33
34 fn retain(
35 &self,
36 id: SerializableTransactionId,
37 control: &StorageReadControl,
38 ) -> VersionResult<SerializableParticipant>;
39
40 fn is_alive(
41 &self,
42 id: SerializableTransactionId,
43 control: &StorageReadControl,
44 ) -> VersionResult<bool>;
45
46 fn reclaim(&self);
47}
48
49pub type SerializableOperation<'a> =
50 dyn FnMut(&mut SerializableGraph, &dyn SerializableLeases) -> VersionResult<()> + 'a;
51
52pub trait SerializableCoordinator: VersionedPersistence {
54 fn with_serializable_admission(
56 &self,
57 control: &StorageReadControl,
58 operation: &mut SerializableOperation<'_>,
59 ) -> VersionResult<()>;
60
61 fn admit_serializable_snapshot(
63 &self,
64 read_only: bool,
65 control: &StorageReadControl,
66 ) -> VersionResult<(SerializableParticipant, Arc<dyn CommittedRecordSnapshot>)> {
67 admit_serializable(self, read_only, control, || self.snapshot(control))
68 }
69
70 fn recover_serializable_participants(&self, control: &StorageReadControl) -> VersionResult<()> {
72 self.with_serializable_admission(control, &mut |graph, leases| {
73 recover(self, graph, leases, control)
74 })
75 }
76}
77
78pub fn admit_serializable<C: SerializableCoordinator + ?Sized, T>(
80 coordinator: &C,
81 read_only: bool,
82 control: &StorageReadControl,
83 capture: impl FnOnce() -> VersionResult<T>,
84) -> VersionResult<(SerializableParticipant, T)> {
85 let mut capture = Some(capture);
86 let mut result = None;
87 coordinator.with_serializable_admission(control, &mut |graph, leases| {
88 let capture = capture.take().ok_or(VersionError::InvalidEncoding(
89 "serializable admission operation was replayed",
90 ))?;
91 recover(coordinator, graph, leases, control)?;
92 let participant =
93 graph.admit_with_lease(read_only, control, |id| leases.retain(id, control))?;
94 let view = capture()?;
95 result = Some((participant, view));
96 Ok(())
97 })?;
98 result.ok_or(VersionError::InvalidEncoding(
99 "serializable admission operation was not invoked",
100 ))
101}
102
103pub(crate) fn recover<C: SerializableCoordinator + ?Sized>(
104 coordinator: &C,
105 graph: &mut SerializableGraph,
106 leases: &dyn SerializableLeases,
107 control: &StorageReadControl,
108) -> VersionResult<()> {
109 graph.reconcile_publications(control, |transaction| {
110 coordinator.commit_status(transaction, control)
111 })?;
112 graph.recover_abandoned(
113 control,
114 |id| leases.is_alive(id, control),
115 |transaction| coordinator.abort(transaction, control),
116 )?;
117 graph.reclaim();
118 leases.reclaim();
119 Ok(())
120}