De-duplicate bridge replacement code

This commit is contained in:
Cecylia Bocovich 2024-03-09 19:20:43 -05:00
parent e6b0cf842a
commit a6c98b8f43
No known key found for this signature in database
GPG Key ID: 009DE379FD9B7B90
1 changed files with 42 additions and 71 deletions

View File

@ -547,85 +547,56 @@ impl BridgeAuth {
let Some(positions) = reachable_bridges.get(bridge) else { let Some(positions) = reachable_bridges.get(bridge) else {
return res; return res;
}; };
if let Some(replacement) = available_bridge { // select replacement:
for (bucketnum, offset) in positions.iter() { // - first try the given bridge
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { // - second try to pick one from the set of available bridges
Some(bridgelines) => *bridgelines, // - third dissolve a spare bucket to create more available bridges
None => return ReplaceSuccess::NotFound, let Some(replacement) = available_bridge.or_else(|| {
self.bridge_table.unallocated_bridges.pop().or_else(|| {
// First get the bucketnums for the replacement bridge in case it is a spare
let mut bucketnums: Vec<u32> = Vec::new();
for (bucketnum, _) in positions.iter() {
bucketnums.push(*bucketnum);
}
let Some(spare) = self
.bridge_table
.spares
.iter()
.find(|x| !bucketnums.contains(x))
.cloned()
else {
return None;
}; };
assert!(bridgelines[*offset] == *bridge); let Ok(_) = self.dissolve_spare_bucket(spare) else {
bridgelines[*offset] = replacement; return None;
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
// Remove the bridge from the reachable bridges and add new bridge
self.bridge_table
.reachable
.insert(replacement, positions.clone());
// Remove the bridge from the bucket
self.bridge_table.reachable.remove(bridge);
}
res = ReplaceSuccess::Replaced
} else if !self.bridge_table.unallocated_bridges.is_empty() {
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
for (bucketnum, offset) in positions.iter() {
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
// This should not happen if the rest of the function is correct, we can assume unwrap will succeed
None => return ReplaceSuccess::NotReplaced,
}; };
assert!(bridgelines[*offset] == *bridge); self.bridge_table.unallocated_bridges.pop()
bridgelines[*offset] = *replacement; })
self.bridge_table.buckets.insert(*bucketnum, bridgelines); }) else {
self.bridge_table
.reachable
.insert(*replacement, positions.clone());
// Remove the bridge from the bucket
self.bridge_table.reachable.remove(bridge);
}
res = ReplaceSuccess::Replaced
} else if !self.bridge_table.spares.is_empty() {
// First get the bucketnums for the replacement bridge in case it is a spare
let mut bucketnums: Vec<u32> = Vec::new();
for (bucketnum, _) in positions.iter() {
bucketnums.push(*bucketnum);
}
// Get the first spare and remove it from the spares set.
let Some(spare) = self
.bridge_table
.spares
.iter()
.find(|x| !bucketnums.contains(x))
.cloned()
else {
return ReplaceSuccess::NotReplaced;
};
let Ok(_) = self.dissolve_spare_bucket(spare) else {
return ReplaceSuccess::NotReplaced;
};
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
for (bucketnum, offset) in positions.iter() {
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
None => return ReplaceSuccess::NotReplaced,
};
assert!(bridgelines[*offset] == *bridge);
bridgelines[*offset] = *replacement;
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
self.bridge_table
.reachable
.insert(*replacement, positions.clone());
// Remove the bridge from the bucket
self.bridge_table.reachable.remove(bridge);
}
res = ReplaceSuccess::Replaced
} else {
println!("No available bridges");
// If there are no available bridges that can be assigned here, the only thing // If there are no available bridges that can be assigned here, the only thing
// that can be done is return an indication that updating the gone bridge // that can be done is return an indication that updating the gone bridge
// didn't work. // didn't work.
// In this case, we do not mark the bridge as unreachable or remove it from the // In this case, we do not mark the bridge as unreachable or remove it from the
// reachable bridges so that we can still find it when a new bridge does become available // reachable bridges so that we can still find it when a new bridge does become available
res = ReplaceSuccess::NotReplaced println!("No available bridges");
return ReplaceSuccess::NotReplaced;
};
for (bucketnum, offset) in positions.iter() {
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
Some(bridgelines) => *bridgelines,
None => return ReplaceSuccess::NotFound,
};
assert!(bridgelines[*offset] == *bridge);
bridgelines[*offset] = replacement;
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
// Remove the bridge from the reachable bridges and add new bridge
self.bridge_table
.reachable
.insert(replacement, positions.clone());
// Remove the bridge from the bucket
self.bridge_table.reachable.remove(bridge);
} }
res = ReplaceSuccess::Replaced;
res res
} }