mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-19 22:13:14 -05:00
first stab at #372
This commit is contained in:
parent
440195c267
commit
bca3877024
@ -115,7 +115,11 @@ impl Bucket {
|
|||||||
self.entries.iter()
|
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
|
// Get number of entries to attempt to purge from bucket
|
||||||
let bucket_len = self.entries.len();
|
let bucket_len = self.entries.len();
|
||||||
|
|
||||||
@ -167,6 +171,11 @@ impl Bucket {
|
|||||||
continue;
|
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
|
// if no references, lets evict it
|
||||||
dead_node_ids.insert(entry.0);
|
dead_node_ids.insert(entry.0);
|
||||||
}
|
}
|
||||||
|
@ -358,9 +358,10 @@ impl RoutingTableInner {
|
|||||||
"Starting routing table buckets purge. Table currently has {} nodes",
|
"Starting routing table buckets purge. Table currently has {} nodes",
|
||||||
self.bucket_entry_count()
|
self.bucket_entry_count()
|
||||||
);
|
);
|
||||||
|
let closest_nodes = BTreeSet::new();
|
||||||
for ck in VALID_CRYPTO_KINDS {
|
for ck in VALID_CRYPTO_KINDS {
|
||||||
for bucket in self.buckets.get_mut(&ck).unwrap().iter_mut() {
|
for bucket in self.buckets.get_mut(&ck).unwrap().iter_mut() {
|
||||||
bucket.kick(0);
|
bucket.kick(0, &closest_nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.all_entries.remove_expired();
|
self.all_entries.remove_expired();
|
||||||
@ -396,11 +397,11 @@ impl RoutingTableInner {
|
|||||||
|
|
||||||
/// Attempt to settle buckets and remove entries down to the desired number
|
/// Attempt to settle buckets and remove entries down to the desired number
|
||||||
/// which may not be possible due extant NodeRefs
|
/// 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 = self.get_bucket_mut(bucket_index);
|
||||||
let bucket_depth = Self::bucket_depth(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
|
// Remove expired entries
|
||||||
self.all_entries.remove_expired();
|
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,
|
crypto: Crypto,
|
||||||
node_id: TypedKey,
|
node_id: TypedKey,
|
||||||
) -> impl Fn(&NodeRefLocked, &NodeRefLocked) -> core::cmp::Ordering {
|
) -> 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::*;
|
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 {
|
impl RoutingTable {
|
||||||
// Kick the queued buckets in the routing table to free dead nodes if necessary
|
// 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
|
// Attempts to keep the size of the routing table down to the bucket depth
|
||||||
@ -15,8 +21,59 @@ impl RoutingTable {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let mut inner = self.inner.write();
|
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 {
|
for bucket_index in kick_queue {
|
||||||
inner.kick_bucket(bucket_index)
|
inner.kick_bucket(bucket_index, &closest_nodes_by_kind[&bucket_index.0]);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user