Remove spare and unallocated bridges rather than replacing them
This commit is contained in:
parent
b771a40a3d
commit
d881cf2fec
|
@ -13,7 +13,6 @@ use serde::{Deserialize, Serialize};
|
|||
use lox_zkp::ProofError;
|
||||
use serde_json::json;
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
|
|
@ -73,6 +73,7 @@ pub enum ReplaceSuccess {
|
|||
NotFound = 0,
|
||||
NotReplaced = 1,
|
||||
Replaced = 2,
|
||||
Removed = 3,
|
||||
}
|
||||
|
||||
/// This error is thrown if the number of buckets/keys in the bridge table
|
||||
|
@ -546,6 +547,25 @@ impl BridgeAuth {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Remove an unallocated resource
|
||||
pub fn remove_unallocated(&mut self, bridge: &BridgeLine) -> ReplaceSuccess {
|
||||
// Check if the bridge is in the unallocated bridges and remove the bridge if so
|
||||
// Bridges in spare buckets should have been moved to the unallocated bridges
|
||||
if self.bridge_table.unallocated_bridges.contains(bridge) {
|
||||
let index = self
|
||||
.bridge_table
|
||||
.unallocated_bridges
|
||||
.iter()
|
||||
.position(|x| x == bridge)
|
||||
.unwrap();
|
||||
self.bridge_table.unallocated_bridges.swap_remove(index);
|
||||
// A bridge that is in the unallocated_bridges is not exactly replaced
|
||||
// but is successfully handled and no further action is needed
|
||||
return ReplaceSuccess::Removed;
|
||||
}
|
||||
ReplaceSuccess::NotFound
|
||||
}
|
||||
|
||||
/// Attempt to remove a bridge that is failing tests and replace it with a bridge from
|
||||
/// available_bridge or from a spare bucket
|
||||
pub fn bridge_replace(
|
||||
|
@ -555,8 +575,23 @@ impl BridgeAuth {
|
|||
) -> ReplaceSuccess {
|
||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||
let Some(positions) = reachable_bridges.get(bridge) else {
|
||||
return ReplaceSuccess::NotFound;
|
||||
return self.remove_unallocated(bridge);
|
||||
};
|
||||
// Check if the bridge is in a spare bucket first, if it is, dissolve the bucket
|
||||
if let Some(spare) = self
|
||||
.bridge_table
|
||||
.spares
|
||||
.iter()
|
||||
.find(|x| positions.iter().any(|(bucketnum, _)| &bucketnum == x))
|
||||
.cloned()
|
||||
{
|
||||
let Ok(_) = self.dissolve_spare_bucket(spare) else {
|
||||
return ReplaceSuccess::NotReplaced;
|
||||
};
|
||||
// Next Check if the bridge is in the unallocated bridges and remove the bridge if so
|
||||
// Bridges in spare buckets should have been moved to the unallocated bridges
|
||||
return self.remove_unallocated(bridge);
|
||||
}
|
||||
// select replacement:
|
||||
// - first try the given bridge
|
||||
// - second try to pick one from the set of available bridges
|
||||
|
|
|
@ -1032,22 +1032,39 @@ fn test_update_bridge() {
|
|||
#[test]
|
||||
fn test_bridge_replace() {
|
||||
// Create 3 open invitation buckets and 3 spare buckets
|
||||
let cases = vec!["not found", "available", "unallocated", "spare", "failed"];
|
||||
let cases = vec![
|
||||
"not found",
|
||||
"available",
|
||||
"unallocated",
|
||||
"use_spare",
|
||||
"remove_spare",
|
||||
"failed",
|
||||
];
|
||||
let num_buckets = 5;
|
||||
let hot_spare = 0;
|
||||
for case in cases {
|
||||
let table_size: usize;
|
||||
let mut th: TestHarness;
|
||||
if String::from(case) != "failed" {
|
||||
th = TestHarness::new();
|
||||
} else {
|
||||
th = TestHarness::new_buckets(num_buckets, hot_spare);
|
||||
match case {
|
||||
"failed" => {
|
||||
th = TestHarness::new_buckets(num_buckets, hot_spare);
|
||||
table_size = th.ba.bridge_table.buckets.len();
|
||||
}
|
||||
"remove_spare" => {
|
||||
th = TestHarness::new_buckets(0, 5);
|
||||
table_size = th.ba.bridge_table.buckets.len();
|
||||
}
|
||||
_ => {
|
||||
th = TestHarness::new();
|
||||
// Ensure that a randomly selected bucket isn't taken from the set of spare bridges
|
||||
table_size = th.ba.bridge_table.buckets.len() - 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Randomly select a bridge to replace
|
||||
let table_size = th.ba.bridge_table.buckets.len();
|
||||
let mut num = 100000;
|
||||
while !th.ba.bridge_table.buckets.contains_key(&num) {
|
||||
num = rand::thread_rng().gen_range(0..th.ba.bridge_table.counter);
|
||||
num = rand::thread_rng().gen_range(0..table_size as u32);
|
||||
}
|
||||
println!("chosen num is: {:?}", num);
|
||||
let replaceable_bucket = *th.ba.bridge_table.buckets.get(&num).unwrap();
|
||||
|
@ -1108,8 +1125,10 @@ fn test_bridge_replace() {
|
|||
.is_some(),
|
||||
"Replacement bridge not added to reachable bridges"
|
||||
);
|
||||
println!("Table Size {:?}", table_size);
|
||||
println!("Bucket length {:?}", th.ba.bridge_table.buckets.len() - 5);
|
||||
assert!(
|
||||
table_size == th.ba.bridge_table.buckets.len(),
|
||||
table_size == th.ba.bridge_table.buckets.len() - 5,
|
||||
"Number of buckets changed size"
|
||||
);
|
||||
assert!(
|
||||
|
@ -1150,7 +1169,7 @@ fn test_bridge_replace() {
|
|||
"Replacement bridge not added to reachable bridges"
|
||||
);
|
||||
assert!(
|
||||
table_size == th.ba.bridge_table.buckets.len(),
|
||||
table_size == th.ba.bridge_table.buckets.len() - 5,
|
||||
"Number of buckets changed size"
|
||||
);
|
||||
assert!(
|
||||
|
@ -1160,7 +1179,7 @@ fn test_bridge_replace() {
|
|||
|
||||
println!("Successfully added unallocated bridgeline");
|
||||
}
|
||||
"spare" => {
|
||||
"use_spare" => {
|
||||
// Case three: available_bridge == null and unallocated_bridges == null
|
||||
assert!(
|
||||
th.ba.bridge_table.unallocated_bridges.is_empty(),
|
||||
|
@ -1180,7 +1199,7 @@ fn test_bridge_replace() {
|
|||
);
|
||||
// Remove a spare bucket to replace bridge, buckets decrease by 1
|
||||
assert!(
|
||||
(table_size - 1) == th.ba.bridge_table.buckets.len(),
|
||||
(table_size - 1) == th.ba.bridge_table.buckets.len() - 5,
|
||||
"Number of buckets changed size"
|
||||
);
|
||||
assert!(
|
||||
|
@ -1190,6 +1209,40 @@ fn test_bridge_replace() {
|
|||
|
||||
println!("Successfully added bridgeline from spare");
|
||||
}
|
||||
"remove_spare" => {
|
||||
// Case three: available_bridge == null and unallocated_bridges == null
|
||||
assert!(
|
||||
th.ba.bridge_table.unallocated_bridges.is_empty(),
|
||||
"Unallocated bridges should have a length of 0"
|
||||
);
|
||||
assert!(
|
||||
th.ba.bridge_replace(replacement_bridge, None) == ReplaceSuccess::Removed,
|
||||
"Bridge was replaced with available spare, instead of being removed"
|
||||
);
|
||||
assert!(
|
||||
th.ba.bridge_table.unallocated_bridges.len() == 2,
|
||||
"Unallocated bridges should have a length of 2"
|
||||
);
|
||||
assert!(
|
||||
th.ba
|
||||
.bridge_table
|
||||
.reachable
|
||||
.get(replacement_bridge)
|
||||
.is_none(),
|
||||
"Replacement bridge still marked as reachable"
|
||||
);
|
||||
// Remove a spare bucket to replace bridge, buckets decrease by 1
|
||||
assert!(
|
||||
(table_size - 1) == th.ba.bridge_table.buckets.len(),
|
||||
"Number of buckets changed size"
|
||||
);
|
||||
assert!(
|
||||
th.ba.bridge_table.unallocated_bridges.len() == 2,
|
||||
"Extra spare bridges not added to unallocated bridges"
|
||||
);
|
||||
|
||||
println!("Successfully removed a spare bridgeline marked to be replaced");
|
||||
}
|
||||
"failed" => {
|
||||
// Case four: available_bridge == None and unallocated_bridges == None and spare buckets == None
|
||||
assert!(
|
||||
|
|
Loading…
Reference in New Issue