De-duplicate bridge replacement code
This commit is contained in:
parent
e6b0cf842a
commit
a6c98b8f43
|
@ -547,85 +547,56 @@ impl BridgeAuth {
|
|||
let Some(positions) = reachable_bridges.get(bridge) else {
|
||||
return res;
|
||||
};
|
||||
if let Some(replacement) = available_bridge {
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||
Some(bridgelines) => *bridgelines,
|
||||
None => return ReplaceSuccess::NotFound,
|
||||
// select replacement:
|
||||
// - first try the given bridge
|
||||
// - second try to pick one from the set of available bridges
|
||||
// - third dissolve a spare bucket to create more available bridges
|
||||
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);
|
||||
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
|
||||
} 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,
|
||||
let Ok(_) = self.dissolve_spare_bucket(spare) else {
|
||||
return None;
|
||||
};
|
||||
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 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");
|
||||
self.bridge_table.unallocated_bridges.pop()
|
||||
})
|
||||
}) else {
|
||||
// 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
|
||||
// didn't work.
|
||||
// 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
|
||||
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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue