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 lox_zkp::ProofError;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,6 +73,7 @@ pub enum ReplaceSuccess {
|
||||||
NotFound = 0,
|
NotFound = 0,
|
||||||
NotReplaced = 1,
|
NotReplaced = 1,
|
||||||
Replaced = 2,
|
Replaced = 2,
|
||||||
|
Removed = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This error is thrown if the number of buckets/keys in the bridge table
|
/// This error is thrown if the number of buckets/keys in the bridge table
|
||||||
|
@ -546,6 +547,25 @@ impl BridgeAuth {
|
||||||
Ok(())
|
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
|
/// Attempt to remove a bridge that is failing tests and replace it with a bridge from
|
||||||
/// available_bridge or from a spare bucket
|
/// available_bridge or from a spare bucket
|
||||||
pub fn bridge_replace(
|
pub fn bridge_replace(
|
||||||
|
@ -555,8 +575,23 @@ impl BridgeAuth {
|
||||||
) -> ReplaceSuccess {
|
) -> ReplaceSuccess {
|
||||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||||
let Some(positions) = reachable_bridges.get(bridge) else {
|
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:
|
// select replacement:
|
||||||
// - first try the given bridge
|
// - first try the given bridge
|
||||||
// - second try to pick one from the set of available bridges
|
// - second try to pick one from the set of available bridges
|
||||||
|
|
|
@ -1032,22 +1032,39 @@ fn test_update_bridge() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bridge_replace() {
|
fn test_bridge_replace() {
|
||||||
// Create 3 open invitation buckets and 3 spare buckets
|
// 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 num_buckets = 5;
|
||||||
let hot_spare = 0;
|
let hot_spare = 0;
|
||||||
for case in cases {
|
for case in cases {
|
||||||
|
let table_size: usize;
|
||||||
let mut th: TestHarness;
|
let mut th: TestHarness;
|
||||||
if String::from(case) != "failed" {
|
match case {
|
||||||
th = TestHarness::new();
|
"failed" => {
|
||||||
} else {
|
th = TestHarness::new_buckets(num_buckets, hot_spare);
|
||||||
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
|
// Randomly select a bridge to replace
|
||||||
let table_size = th.ba.bridge_table.buckets.len();
|
|
||||||
let mut num = 100000;
|
let mut num = 100000;
|
||||||
while !th.ba.bridge_table.buckets.contains_key(&num) {
|
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);
|
println!("chosen num is: {:?}", num);
|
||||||
let replaceable_bucket = *th.ba.bridge_table.buckets.get(&num).unwrap();
|
let replaceable_bucket = *th.ba.bridge_table.buckets.get(&num).unwrap();
|
||||||
|
@ -1108,8 +1125,10 @@ fn test_bridge_replace() {
|
||||||
.is_some(),
|
.is_some(),
|
||||||
"Replacement bridge not added to reachable bridges"
|
"Replacement bridge not added to reachable bridges"
|
||||||
);
|
);
|
||||||
|
println!("Table Size {:?}", table_size);
|
||||||
|
println!("Bucket length {:?}", th.ba.bridge_table.buckets.len() - 5);
|
||||||
assert!(
|
assert!(
|
||||||
table_size == th.ba.bridge_table.buckets.len(),
|
table_size == th.ba.bridge_table.buckets.len() - 5,
|
||||||
"Number of buckets changed size"
|
"Number of buckets changed size"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -1150,7 +1169,7 @@ fn test_bridge_replace() {
|
||||||
"Replacement bridge not added to reachable bridges"
|
"Replacement bridge not added to reachable bridges"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
table_size == th.ba.bridge_table.buckets.len(),
|
table_size == th.ba.bridge_table.buckets.len() - 5,
|
||||||
"Number of buckets changed size"
|
"Number of buckets changed size"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -1160,7 +1179,7 @@ fn test_bridge_replace() {
|
||||||
|
|
||||||
println!("Successfully added unallocated bridgeline");
|
println!("Successfully added unallocated bridgeline");
|
||||||
}
|
}
|
||||||
"spare" => {
|
"use_spare" => {
|
||||||
// Case three: available_bridge == null and unallocated_bridges == null
|
// Case three: available_bridge == null and unallocated_bridges == null
|
||||||
assert!(
|
assert!(
|
||||||
th.ba.bridge_table.unallocated_bridges.is_empty(),
|
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
|
// Remove a spare bucket to replace bridge, buckets decrease by 1
|
||||||
assert!(
|
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"
|
"Number of buckets changed size"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -1190,6 +1209,40 @@ fn test_bridge_replace() {
|
||||||
|
|
||||||
println!("Successfully added bridgeline from spare");
|
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" => {
|
"failed" => {
|
||||||
// Case four: available_bridge == None and unallocated_bridges == None and spare buckets == None
|
// Case four: available_bridge == None and unallocated_bridges == None and spare buckets == None
|
||||||
assert!(
|
assert!(
|
||||||
|
|
Loading…
Reference in New Issue