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
|
/// them. When a new Migration credential is needed, a bucket is
|
||||||
/// removed from this set and used for that purpose.
|
/// removed from this set and used for that purpose.
|
||||||
pub spares: HashSet<u32>,
|
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 date the buckets were last encrypted to make the encbucket.
|
||||||
///
|
|
||||||
/// The encbucket must be rebuilt each day so that the Bucket
|
/// The encbucket must be rebuilt each day so that the Bucket
|
||||||
/// Reachability credentials in the buckets can be refreshed.
|
/// Reachability credentials in the buckets can be refreshed.
|
||||||
pub date_last_enc: u32,
|
pub date_last_enc: u32,
|
||||||
|
|
|
@ -366,11 +366,125 @@ impl BridgeAuth {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !res {
|
// If this is returned, we assume that the bridge wasn't found in the bridge table
|
||||||
// Assume the bridge is new and should be added to unallocated bridges or else a new bucket
|
// 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
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue