Added bridge replacement
This commit is contained in:
parent
11d4678be8
commit
83c7916805
|
@ -224,8 +224,17 @@ pub struct BridgeTable {
|
|||
/// them. When a new Migration credential is needed, a bucket is
|
||||
/// removed from this set and used for that purpose.
|
||||
pub spares: HashSet<u32>,
|
||||
/// bucket ids of "recyclable" buckets. These buckets have not been handed out
|
||||
/// to users, nor do they have any Migration credentials pointing to
|
||||
/// them. When a single bridge is needed and there are no more readily available bridges,
|
||||
/// bridges are taken from a bucket of hot spares, making the unallocated spare bucket empty
|
||||
/// but still useable as it has not been handed out previously.
|
||||
pub recyclable: HashSet<u32>,
|
||||
/// In some instances a single bridge may need to be added to a bucket
|
||||
/// In some instances a single bridge may need to be added to a bucket
|
||||
/// In that case, a spare bucket will be removed from the set of spare bridges. One
|
||||
pub unallocated_bridges: Vec<BridgeLine>,
|
||||
/// The date the buckets were last encrypted to make the encbucket.
|
||||
///
|
||||
/// The encbucket must be rebuilt each day so that the Bucket
|
||||
/// Reachability credentials in the buckets can be refreshed.
|
||||
pub date_last_enc: u32,
|
||||
|
|
|
@ -366,11 +366,125 @@ impl BridgeAuth {
|
|||
return res;
|
||||
}
|
||||
}
|
||||
if !res {
|
||||
// Assume the bridge is new and should be added to unallocated bridges or else a new bucket
|
||||
// If this is returned, we assume that the bridge wasn't found in the bridge table
|
||||
// and therefore should be treated as a "new bridge"
|
||||
res
|
||||
}
|
||||
|
||||
pub fn bridge_replace(
|
||||
&mut self,
|
||||
bridge: &BridgeLine,
|
||||
available_bridge: Option<&BridgeLine>,
|
||||
bdb: &mut BridgeDb,
|
||||
) -> bool {
|
||||
let mut res: bool = false;
|
||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||
if let Some(positions) = reachable_bridges.get(bridge) {
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
// Remove the bridge from the bucket
|
||||
assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge);
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
if available_bridge.is_some() {
|
||||
self.bridge_table.buckets[*bucketnum as usize][*offset] =
|
||||
*available_bridge.unwrap();
|
||||
// Remove the bridge from the reachable bridges and add new bridge
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(*available_bridge.unwrap(), positions.clone());
|
||||
res = true
|
||||
} else if !self.bridge_table.unallocated_bridges.is_empty() {
|
||||
self.bridge_table.buckets[*bucketnum as usize][*offset] =
|
||||
self.bridge_table.unallocated_bridges.pop().unwrap();
|
||||
// Remove the bridge from the reachable bridges and add new bridge
|
||||
self.bridge_table.reachable.insert(
|
||||
self.bridge_table.unallocated_bridges.pop().unwrap(),
|
||||
positions.clone(),
|
||||
);
|
||||
res = true
|
||||
} else if !self.bridge_table.spares.is_empty() {
|
||||
// Get the first spare and remove it from the spares
|
||||
// set.
|
||||
let spare = *self.bridge_table.spares.iter().next().unwrap();
|
||||
self.bridge_table.spares.remove(&spare);
|
||||
// Indicate the removed bucket as a recyclable bucket
|
||||
self.bridge_table.recyclable.insert(spare);
|
||||
// Get the actual bridges from the spare bucket
|
||||
let mut replacement: &BridgeLine = &BridgeLine::default();
|
||||
// Make the first spare the replacement bridge, add the others to the set of
|
||||
// unallocated_bridges
|
||||
let spare_bucket = self.bridge_table.buckets[spare as usize].clone();
|
||||
for spare_bridge in spare_bucket.iter() {
|
||||
if replacement.port > 0 {
|
||||
self.bridge_table.unallocated_bridges.push(*spare_bridge);
|
||||
} else {
|
||||
replacement = spare_bridge;
|
||||
}
|
||||
}
|
||||
self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement;
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(*replacement, positions.clone());
|
||||
res = true
|
||||
}
|
||||
// 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.
|
||||
|
||||
// Now we should check that the bucket hasn't become "blocked" due to having no available
|
||||
// bridges
|
||||
if !res {
|
||||
// Count how many bridges in this bucket are reachable
|
||||
let numreachable = self.bridge_table.buckets[*bucketnum as usize]
|
||||
.iter()
|
||||
.filter(|br| self.bridge_table.reachable.get(br).is_some())
|
||||
.count();
|
||||
|
||||
// Is this bucket an open-invitation bucket?
|
||||
if bdb.openinv_buckets.contains(bucketnum) {
|
||||
bdb.openinv_buckets.remove(bucketnum);
|
||||
self.trustup_migration_table.table.remove(bucketnum);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Has the bucket fallen below the
|
||||
// threshold?
|
||||
if numreachable == MIN_BUCKET_REACHABILITY {
|
||||
// This bucket is now unreachable. Get a spare bucket
|
||||
if self.bridge_table.spares.is_empty() {
|
||||
// Uh, oh. No spares available. Just delete any
|
||||
// migrations leading to this bucket.
|
||||
self.trustup_migration_table
|
||||
.table
|
||||
.retain(|_, &mut v| v != *bucketnum);
|
||||
self.blockage_migration_table
|
||||
.table
|
||||
.retain(|_, &mut v| v != *bucketnum);
|
||||
} else {
|
||||
// Get the first spare and remove it from the spares
|
||||
// set.
|
||||
let spare = *self.bridge_table.spares.iter().next().unwrap();
|
||||
self.bridge_table.spares.remove(&spare);
|
||||
// Add a blockage migration from this bucket to the spare
|
||||
self.blockage_migration_table
|
||||
.table
|
||||
.insert(*bucketnum, spare);
|
||||
// Remove any trust upgrade migrations to this
|
||||
// bucket
|
||||
self.trustup_migration_table
|
||||
.table
|
||||
.retain(|_, &mut v| v != *bucketnum);
|
||||
// Change any blockage migrations with this bucket
|
||||
// as the destination to the spare
|
||||
for (_, v) in self.blockage_migration_table.table.iter_mut() {
|
||||
if *v == *bucketnum {
|
||||
*v = spare;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue