ozzy_replication/driver/
receive.rs1use super::{DriverError, ReplicaDriver, Role};
5use crate::wire::Control;
6use crate::{
7 Admission, PreparedOperation, ReplicationError, Scope, StartView, ViewChangeError, VoterIndex,
8};
9use ozzy_proto::NodeId;
10use std::time::Duration;
11
12impl ReplicaDriver {
13 pub fn receive(
26 &mut self,
27 from: NodeId,
28 message: Control,
29 now: Duration,
30 ) -> Result<Option<StartView>, DriverError> {
31 self.observe_time(now)?;
32 let voter = self.configuration.voter_index(from)?;
33 if voter == self.local {
34 return Err(ReplicationError::WrongRole.into());
35 }
36 let scope = message.scope();
37 if scope
38 != (Scope {
39 view: scope.view,
40 ..self.configuration.scope()
41 })
42 {
43 return Err(ReplicationError::ScopeMismatch.into());
44 }
45 if let Control::ExitView(_) = message {
46 self.receive_exit(voter, scope)?;
47 return Ok(None);
48 }
49 if scope.view < self.scope().view {
50 return Ok(None);
51 }
52 self.check_role(voter, message)?;
53 if let Control::StartViewChange(_) = message {
54 self.require_healthy()?;
55 if scope.view > self.scope().view {
58 self.change_view(scope.view)?;
59 }
60 if scope.view != self.scope().view {
61 return Ok(None);
62 }
63 }
64 if scope.view > self.scope().view {
65 self.change_view(scope.view)?;
66 }
67 match &mut self.role {
68 Role::Normal(_) => self.receive_normal(from, voter, message, now)?,
69 Role::ViewChanging(changing) => match message {
70 Control::StartViewChange(start) => changing.receive_start(from, start)?,
71 Control::DoViewChange(report) => changing.receive_report(from, report)?,
72 Control::StartView(start) => return Ok(Some(start)),
73 Control::Commit(_) | Control::PrepareOk { .. } | Control::ExitView(_) => {}
74 },
75 Role::Installing(installing) => installing.observe_view(from, scope)?,
76 Role::Fenced(_) => return Err(ViewChangeError::Faulted.into()),
77 }
78 Ok(None)
79 }
80
81 fn check_role(&self, voter: VoterIndex, message: Control) -> Result<(), DriverError> {
84 let primary = VoterIndex::primary(message.scope().view);
85 match message {
86 Control::Commit(_) | Control::StartView(_) if voter != primary => {
87 Err(ReplicationError::WrongRole.into())
88 }
89 Control::PrepareOk { .. } | Control::DoViewChange(_) if self.local != primary => {
90 Err(ReplicationError::WrongRole.into())
91 }
92 _ => Ok(()),
93 }
94 }
95
96 fn receive_normal(
99 &mut self,
100 from: NodeId,
101 voter: VoterIndex,
102 message: Control,
103 now: Duration,
104 ) -> Result<(), DriverError> {
105 let Role::Normal(normal) = &mut self.role else {
106 return Ok(());
107 };
108 let committed = normal.snapshot().committed;
109 match message {
110 Control::Commit(commit) => {
111 normal.receive_commit(from, commit)?;
112 self.contact_deadline = now.saturating_add(self.timing.primary_timeout);
113 }
114 Control::PrepareOk { ack, .. } => normal.receive_ack(from, ack)?,
115 Control::StartView(start) => {
116 normal.observe_installed_start(from, start)?;
117 self.contact_deadline = now.saturating_add(self.timing.primary_timeout);
118 }
119 _ => return Ok(()),
120 }
121 if let Some(prefix) = message.acknowledged()
122 && let Some(start) = normal.start_view()?
123 && prefix == start.accepted
124 && start.accepted.op < normal.snapshot().committed.op
125 {
126 self.activation_pending.insert(voter);
129 }
130 if normal.snapshot().committed != committed {
131 self.progress_deadline = now.saturating_add(self.progress_timeout());
132 }
133 Ok(())
134 }
135
136 pub fn prepare(
140 &mut self,
141 from: NodeId,
142 scope: Scope,
143 operations: &[PreparedOperation],
144 now: Duration,
145 ) -> Result<Admission, DriverError> {
146 self.observe_time(now)?;
147 let voter = self.configuration.voter_index(from)?;
148 if scope
149 != (Scope {
150 view: scope.view,
151 ..self.configuration.scope()
152 })
153 {
154 return Err(ReplicationError::ScopeMismatch.into());
155 }
156 if voter != VoterIndex::primary(scope.view) {
157 return Err(ReplicationError::WrongRole.into());
158 }
159 if scope.view > self.scope().view {
160 self.change_view(scope.view)?;
161 }
162 let Role::Normal(normal) = &mut self.role else {
163 return Err(ReplicationError::NotNormal.into());
164 };
165 let previous = normal.snapshot();
166 let admitted = normal.prepare(from, scope, operations)?;
167 if normal.snapshot().accepted != previous.accepted
168 && previous.accepted == previous.committed
169 && previous.ready_for_appends
170 {
171 self.progress_deadline = now.saturating_add(self.timing.primary_timeout);
172 }
173 if normal.snapshot().accepted != previous.accepted
174 && previous.accepted.op == previous.journal.durable
175 {
176 self.persistence_deadline = now.saturating_add(self.timing.primary_timeout);
177 }
178 self.contact_deadline = now.saturating_add(self.timing.primary_timeout);
179 Ok(admitted)
180 }
181}