mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-12-28 00:39:25 -05:00
first stab at #372
This commit is contained in:
parent
440195c267
commit
bca3877024
@ -115,7 +115,11 @@ impl Bucket {
|
||||
self.entries.iter()
|
||||
}
|
||||
|
||||
pub(super) fn kick(&mut self, bucket_depth: usize) -> Option<BTreeSet<PublicKey>> {
|
||||
pub(super) fn kick(
|
||||
&mut self,
|
||||
bucket_depth: usize,
|
||||
closest_nodes: &BTreeSet<PublicKey>,
|
||||
) -> Option<BTreeSet<PublicKey>> {
|
||||
// Get number of entries to attempt to purge from bucket
|
||||
let bucket_len = self.entries.len();
|
||||
|
||||
@ -167,6 +171,11 @@ impl Bucket {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this entry is one of our N closest entries, don't drop it
|
||||
if closest_nodes.contains(&entry.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if no references, lets evict it
|
||||
dead_node_ids.insert(entry.0);
|
||||
}
|
||||
|
@ -358,9 +358,10 @@ impl RoutingTableInner {
|
||||
"Starting routing table buckets purge. Table currently has {} nodes",
|
||||
self.bucket_entry_count()
|
||||
);
|
||||
let closest_nodes = BTreeSet::new();
|
||||
for ck in VALID_CRYPTO_KINDS {
|
||||
for bucket in self.buckets.get_mut(&ck).unwrap().iter_mut() {
|
||||
bucket.kick(0);
|
||||
bucket.kick(0, &closest_nodes);
|
||||
}
|
||||
}
|
||||
self.all_entries.remove_expired();
|
||||
@ -396,11 +397,11 @@ impl RoutingTableInner {
|
||||
|
||||
/// Attempt to settle buckets and remove entries down to the desired number
|
||||
/// which may not be possible due extant NodeRefs
|
||||
pub fn kick_bucket(&mut self, bucket_index: BucketIndex) {
|
||||
pub fn kick_bucket(&mut self, bucket_index: BucketIndex, closest_nodes: &BTreeSet<PublicKey>) {
|
||||
let bucket = self.get_bucket_mut(bucket_index);
|
||||
let bucket_depth = Self::bucket_depth(bucket_index);
|
||||
|
||||
if let Some(_dead_node_ids) = bucket.kick(bucket_depth) {
|
||||
if let Some(_dead_node_ids) = bucket.kick(bucket_depth, closest_nodes) {
|
||||
// Remove expired entries
|
||||
self.all_entries.remove_expired();
|
||||
|
||||
@ -1252,7 +1253,7 @@ impl RoutingTableInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_closest_noderef_sort(
|
||||
pub(crate) fn make_closest_noderef_sort(
|
||||
crypto: Crypto,
|
||||
node_id: TypedKey,
|
||||
) -> impl Fn(&NodeRefLocked, &NodeRefLocked) -> core::cmp::Ordering {
|
||||
@ -1280,3 +1281,19 @@ fn make_closest_noderef_sort(
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn make_closest_node_id_sort(
|
||||
crypto: Crypto,
|
||||
node_id: TypedKey,
|
||||
) -> impl Fn(&CryptoKey, &CryptoKey) -> core::cmp::Ordering {
|
||||
let kind = node_id.kind;
|
||||
// Get cryptoversion to check distance with
|
||||
let vcrypto = crypto.get(kind).unwrap();
|
||||
|
||||
move |a: &CryptoKey, b: &CryptoKey| -> core::cmp::Ordering {
|
||||
// distance is the next metric, closer nodes first
|
||||
let da = vcrypto.distance(a, &node_id.value);
|
||||
let db = vcrypto.distance(b, &node_id.value);
|
||||
da.cmp(&db)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
use super::*;
|
||||
|
||||
/// How many 'reliable' nodes closest to our own node id to keep
|
||||
const KEEP_N_CLOSEST_RELIABLE_ENTRIES_COUNT: usize = 16;
|
||||
|
||||
/// How many 'unreliable' nodes closest to our own node id to keep
|
||||
const KEEP_N_CLOSEST_UNRELIABLE_ENTRIES_COUNT: usize = 8;
|
||||
|
||||
impl RoutingTable {
|
||||
// Kick the queued buckets in the routing table to free dead nodes if necessary
|
||||
// Attempts to keep the size of the routing table down to the bucket depth
|
||||
@ -15,8 +21,59 @@ impl RoutingTable {
|
||||
.into_iter()
|
||||
.collect();
|
||||
let mut inner = self.inner.write();
|
||||
|
||||
// Get our closest nodes for each crypto kind
|
||||
let mut closest_nodes_by_kind = BTreeMap::<CryptoKind, BTreeSet<PublicKey>>::new();
|
||||
|
||||
for kind in VALID_CRYPTO_KINDS {
|
||||
let our_node_id = self.node_id(kind);
|
||||
let Some(buckets) = inner.buckets.get(&kind) else {
|
||||
continue;
|
||||
};
|
||||
let sort = make_closest_node_id_sort(self.crypto(), our_node_id);
|
||||
|
||||
let mut closest_nodes = BTreeSet::<CryptoKey>::new();
|
||||
let mut closest_unreliable_count = 0usize;
|
||||
let mut closest_reliable_count = 0usize;
|
||||
|
||||
// Iterate buckets backward, sort entries by closest distance first
|
||||
'outer: for bucket in buckets.iter().rev() {
|
||||
let mut entries = bucket.entries().collect::<Vec<_>>();
|
||||
entries.sort_by(|a, b| sort(a.0, b.0));
|
||||
for (key, entry) in entries {
|
||||
let state = entry.with(&inner, |_rti, e| e.state(cur_ts));
|
||||
match state {
|
||||
BucketEntryState::Dead => {
|
||||
// Do nothing with dead entries
|
||||
}
|
||||
BucketEntryState::Unreliable => {
|
||||
// Add to closest unreliable nodes list
|
||||
if closest_unreliable_count < KEEP_N_CLOSEST_UNRELIABLE_ENTRIES_COUNT {
|
||||
closest_nodes.insert(*key);
|
||||
closest_unreliable_count += 1;
|
||||
}
|
||||
}
|
||||
BucketEntryState::Reliable => {
|
||||
// Add to closest reliable nodes list
|
||||
if closest_reliable_count < KEEP_N_CLOSEST_RELIABLE_ENTRIES_COUNT {
|
||||
closest_nodes.insert(*key);
|
||||
closest_reliable_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if closest_unreliable_count == KEEP_N_CLOSEST_UNRELIABLE_ENTRIES_COUNT
|
||||
&& closest_reliable_count == KEEP_N_CLOSEST_RELIABLE_ENTRIES_COUNT
|
||||
{
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closest_nodes_by_kind.insert(kind, closest_nodes);
|
||||
}
|
||||
|
||||
for bucket_index in kick_queue {
|
||||
inner.kick_bucket(bucket_index)
|
||||
inner.kick_bucket(bucket_index, &closest_nodes_by_kind[&bucket_index.0]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user