Skip to content

Commit c2247df

Browse files
authored
Removing panic paths by only destructuring once (#1523)
We have a few functions of the form ```rust match message { Message::RepairAckId { .. } => self.on_repair_ack(message), // ... } // ...later in the file: fn on_repair_ack(&self, message: &Message) { let Message::RepairAckId { repair_id } = message else { panic!() }; // ... } ``` This PR refactors those functions to only destructure the message once, passing its inner fields into the function which needs them. It makes the code shorter _and_ removes possible panic paths.
1 parent 982b44b commit c2247df

File tree

2 files changed

+33
-93
lines changed

2 files changed

+33
-93
lines changed

upstairs/src/downstairs.rs

Lines changed: 20 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,7 @@ impl Downstairs {
17141714
pub(crate) fn on_reconciliation_ack(
17151715
&mut self,
17161716
client_id: ClientId,
1717-
m: Message,
1717+
repair_id: ReconciliationId,
17181718
up_state: &UpstairsState,
17191719
) -> bool {
17201720
let Some(next) = self.reconcile_current_work.as_mut() else {
@@ -1742,10 +1742,6 @@ impl Downstairs {
17421742
return false;
17431743
}
17441744

1745-
let Message::RepairAckId { repair_id } = m else {
1746-
panic!("invalid message {m:?} for on_reconciliation_ack");
1747-
};
1748-
17491745
if self.clients[client_id].on_reconciliation_job_done(repair_id, next) {
17501746
self.reconcile_current_work = None;
17511747
self.reconcile_repair_needed -= 1;
@@ -1763,17 +1759,11 @@ impl Downstairs {
17631759
pub(crate) fn on_reconciliation_failed(
17641760
&mut self,
17651761
client_id: ClientId,
1766-
m: Message,
1762+
repair_id: ReconciliationId,
1763+
extent_id: ExtentId,
1764+
error: CrucibleError,
17671765
up_state: &UpstairsState,
17681766
) {
1769-
let Message::ExtentError {
1770-
repair_id,
1771-
extent_id,
1772-
error,
1773-
} = m
1774-
else {
1775-
panic!("invalid message {m:?}");
1776-
};
17771767
error!(
17781768
self.clients[client_id].log,
17791769
"extent {extent_id} error on job {repair_id}: {error}"
@@ -6119,9 +6109,7 @@ pub(crate) mod test {
61196109
// Send an ack to trigger the reconciliation state check
61206110
let nw = ds.on_reconciliation_ack(
61216111
ClientId::new(0),
6122-
Message::RepairAckId {
6123-
repair_id: close_id,
6124-
},
6112+
close_id,
61256113
&UpstairsState::Active,
61266114
);
61276115
assert!(!nw);
@@ -6166,28 +6154,15 @@ pub(crate) mod test {
61666154
ds.send_next_reconciliation_req();
61676155

61686156
// Downstairs 0 and 2 are okay, but 1 failed (for some reason!)
6169-
let msg = Message::RepairAckId { repair_id: rep_id };
6170-
assert!(!ds.on_reconciliation_ack(
6171-
ClientId::new(0),
6172-
msg.clone(),
6173-
&up_state
6174-
));
6157+
assert!(!ds.on_reconciliation_ack(ClientId::new(0), rep_id, &up_state));
61756158
ds.on_reconciliation_failed(
61766159
ClientId::new(1),
6177-
Message::ExtentError {
6178-
repair_id: rep_id,
6179-
extent_id: ExtentId(1),
6180-
error: CrucibleError::GenericError(
6181-
"test extent error".to_owned(),
6182-
),
6183-
},
6160+
rep_id,
6161+
ExtentId(1),
6162+
CrucibleError::GenericError("test extent error".to_owned()),
61846163
&up_state,
61856164
);
6186-
assert!(!ds.on_reconciliation_ack(
6187-
ClientId::new(2),
6188-
msg.clone(),
6189-
&up_state
6190-
));
6165+
assert!(!ds.on_reconciliation_ack(ClientId::new(2), rep_id, &up_state));
61916166

61926167
// Getting the next work to do should verify the previous is done,
61936168
// and handle a state change for a downstairs.
@@ -6255,34 +6230,18 @@ pub(crate) mod test {
62556230

62566231
// Ack the close job. Reconciliation isn't done at this point, because
62576232
// there's another job in the task list.
6258-
let msg = Message::RepairAckId {
6259-
repair_id: close_id,
6260-
};
62616233
for i in ClientId::iter() {
6262-
assert!(!ds.on_reconciliation_ack(i, msg.clone(), &up_state));
6234+
assert!(!ds.on_reconciliation_ack(i, close_id, &up_state));
62636235
}
62646236

62656237
// The third ack will have sent the next reconciliation job
62666238
assert!(ds.reconcile_task_list.is_empty());
62676239

62686240
// Now, make sure we consider this done only after all three are done
6269-
let msg = Message::RepairAckId { repair_id: rep_id };
6270-
assert!(!ds.on_reconciliation_ack(
6271-
ClientId::new(0),
6272-
msg.clone(),
6273-
&up_state
6274-
));
6275-
assert!(!ds.on_reconciliation_ack(
6276-
ClientId::new(1),
6277-
msg.clone(),
6278-
&up_state
6279-
));
6241+
assert!(!ds.on_reconciliation_ack(ClientId::new(0), rep_id, &up_state));
6242+
assert!(!ds.on_reconciliation_ack(ClientId::new(1), rep_id, &up_state));
62806243
// The third ack finishes reconciliation!
6281-
assert!(ds.on_reconciliation_ack(
6282-
ClientId::new(2),
6283-
msg.clone(),
6284-
&up_state
6285-
));
6244+
assert!(ds.on_reconciliation_ack(ClientId::new(2), rep_id, &up_state));
62866245
assert_eq!(ds.reconcile_repair_needed, 0);
62876246
assert_eq!(ds.reconcile_repaired, 2);
62886247
}
@@ -6328,19 +6287,10 @@ pub(crate) mod test {
63286287
assert_eq!(job.state[ClientId::new(1)], ReconcileIOState::InProgress);
63296288
assert_eq!(job.state[ClientId::new(2)], ReconcileIOState::InProgress);
63306289

6331-
let msg = Message::RepairAckId { repair_id: rep_id };
6332-
assert!(!ds.on_reconciliation_ack(
6333-
ClientId::new(1),
6334-
msg.clone(),
6335-
&up_state
6336-
));
6290+
assert!(!ds.on_reconciliation_ack(ClientId::new(1), rep_id, &up_state));
63376291
// The second ack finishes reconciliation, because it was skipped for
63386292
// client 0 (which was the source of repairs).
6339-
assert!(ds.on_reconciliation_ack(
6340-
ClientId::new(2),
6341-
msg.clone(),
6342-
&up_state
6343-
));
6293+
assert!(ds.on_reconciliation_ack(ClientId::new(2), rep_id, &up_state));
63446294
assert_eq!(ds.reconcile_repair_needed, 0);
63456295
assert_eq!(ds.reconcile_repaired, 1);
63466296
}
@@ -6375,11 +6325,8 @@ pub(crate) mod test {
63756325

63766326
// If we get back an ack from client 0, something has gone terribly
63776327
// wrong (because the jobs should have been skipped for it)
6378-
ds.on_reconciliation_ack(
6379-
ClientId::new(0),
6380-
Message::RepairAckId { repair_id: rep_id },
6381-
&up_state,
6382-
); // this should panic!
6328+
ds.on_reconciliation_ack(ClientId::new(0), rep_id, &up_state);
6329+
// this should panic!
63836330
}
63846331

63856332
#[test]
@@ -6414,17 +6361,8 @@ pub(crate) mod test {
64146361
assert!(!ds.send_next_reconciliation_req());
64156362

64166363
// Now, make sure we consider this done only after all three are done
6417-
let msg = Message::RepairAckId { repair_id: rep_id };
6418-
assert!(!ds.on_reconciliation_ack(
6419-
ClientId::new(1),
6420-
msg.clone(),
6421-
&up_state
6422-
));
6423-
assert!(!ds.on_reconciliation_ack(
6424-
ClientId::new(2),
6425-
msg.clone(),
6426-
&up_state
6427-
));
6364+
assert!(!ds.on_reconciliation_ack(ClientId::new(1), rep_id, &up_state));
6365+
assert!(!ds.on_reconciliation_ack(ClientId::new(2), rep_id, &up_state));
64286366
// don't finish
64296367

64306368
ds.send_next_reconciliation_req(); // panics!

upstairs/src/upstairs.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,17 +1684,23 @@ impl Upstairs {
16841684
}
16851685
}
16861686

1687-
Message::ExtentError { .. } => {
1687+
Message::ExtentError {
1688+
repair_id,
1689+
extent_id,
1690+
error,
1691+
} => {
16881692
self.downstairs.on_reconciliation_failed(
16891693
client_id,
1690-
m,
1694+
repair_id,
1695+
extent_id,
1696+
error,
16911697
&self.state,
16921698
);
16931699
}
1694-
Message::RepairAckId { .. } => {
1700+
Message::RepairAckId { repair_id } => {
16951701
if self.downstairs.on_reconciliation_ack(
16961702
client_id,
1697-
m,
1703+
repair_id,
16981704
&self.state,
16991705
) {
17001706
// reconciliation is done, great work everyone
@@ -1706,8 +1712,8 @@ impl Upstairs {
17061712
self.on_no_longer_active(client_id, m);
17071713
}
17081714

1709-
Message::UuidMismatch { .. } => {
1710-
self.on_uuid_mismatch(client_id, m);
1715+
Message::UuidMismatch { expected_id } => {
1716+
self.on_uuid_mismatch(client_id, expected_id);
17111717
}
17121718

17131719
// These are all messages that we send out, so we shouldn't see them
@@ -1953,11 +1959,7 @@ impl Upstairs {
19531959
self.set_inactive(CrucibleError::NoLongerActive);
19541960
}
19551961

1956-
fn on_uuid_mismatch(&mut self, client_id: ClientId, m: Message) {
1957-
let Message::UuidMismatch { expected_id } = m else {
1958-
panic!("called on_uuid_mismatch on invalid message {m:?}");
1959-
};
1960-
1962+
fn on_uuid_mismatch(&mut self, client_id: ClientId, expected_id: Uuid) {
19611963
let client_log = &self.downstairs.clients[client_id].log;
19621964
error!(
19631965
client_log,

0 commit comments

Comments
 (0)