With pinger its not entirely bad now, but still pretty horrible

This commit is contained in:
Igor Katson 2023-11-30 13:58:33 +00:00
parent 8d58a9f419
commit fee2690aae
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
2 changed files with 49 additions and 59 deletions

View file

@ -14,7 +14,7 @@ use crate::{
self, CompactNodeInfo, ErrorDescription, FindNodeRequest, GetPeersRequest, Message, self, CompactNodeInfo, ErrorDescription, FindNodeRequest, GetPeersRequest, Message,
MessageKind, Node, PingRequest, Response, MessageKind, Node, PingRequest, Response,
}, },
routing_table::{InsertResult, RoutingTable}, routing_table::{InsertResult, NodeStatus, RoutingTable},
INACTIVITY_TIMEOUT, REQUERY_INTERVAL, RESPONSE_TIMEOUT, INACTIVITY_TIMEOUT, REQUERY_INTERVAL, RESPONSE_TIMEOUT,
}; };
use anyhow::{bail, Context}; use anyhow::{bail, Context};
@ -109,12 +109,10 @@ impl RecursiveRequestCallbacks for RecursiveRequestCallbacksGetPeers {
struct RecursiveRequestCallbacksFindNodes {} struct RecursiveRequestCallbacksFindNodes {}
impl RecursiveRequestCallbacks for RecursiveRequestCallbacksFindNodes { impl RecursiveRequestCallbacks for RecursiveRequestCallbacksFindNodes {
fn on_request_start(&self, req: &RecursiveRequest<Self>, target_node: Id20, addr: SocketAddr) { fn on_request_start(&self, req: &RecursiveRequest<Self>, target_node: Id20, addr: SocketAddr) {
match req.dht.routing_table_add_node(target_node, addr) { let mut rt = req.dht.routing_table.write();
match rt.add_node(target_node, addr) {
InsertResult::WasExisting | InsertResult::ReplacedBad(_) | InsertResult::Added => { InsertResult::WasExisting | InsertResult::ReplacedBad(_) | InsertResult::Added => {
req.dht rt.mark_outgoing_request(&target_node);
.routing_table
.write()
.mark_outgoing_request(&target_node);
} }
InsertResult::Ignored => {} InsertResult::Ignored => {}
} }
@ -490,15 +488,12 @@ pub struct DhtState {
rate_limiter: RateLimiter, rate_limiter: RateLimiter,
// This is to send raw messages // This is to send raw messages
worker_sender: UnboundedSender<WorkerSendRequest>, worker_sender: UnboundedSender<WorkerSendRequest>,
// This is to send pings.
ping_sender: UnboundedSender<(Id20, SocketAddr)>,
} }
impl DhtState { impl DhtState {
fn new_internal( fn new_internal(
id: Id20, id: Id20,
sender: UnboundedSender<WorkerSendRequest>, sender: UnboundedSender<WorkerSendRequest>,
ping_sender: UnboundedSender<(Id20, SocketAddr)>,
routing_table: Option<RoutingTable>, routing_table: Option<RoutingTable>,
listen_addr: SocketAddr, listen_addr: SocketAddr,
) -> Self { ) -> Self {
@ -510,7 +505,6 @@ impl DhtState {
routing_table: RwLock::new(routing_table), routing_table: RwLock::new(routing_table),
worker_sender: sender, worker_sender: sender,
listen_addr, listen_addr,
ping_sender,
rate_limiter: make_rate_limiter(), rate_limiter: make_rate_limiter(),
} }
} }
@ -716,14 +710,6 @@ impl DhtState {
routing_table_size: self.routing_table.read().len(), routing_table_size: self.routing_table.read().len(),
} }
} }
fn routing_table_add_node(self: &Arc<Self>, id: Id20, addr: SocketAddr) -> InsertResult {
let res = self.routing_table.write().add_node(id, addr, |id, addr| {
let _ = self.ping_sender.send((id, addr));
true
});
res
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -813,15 +799,20 @@ impl DhtWorker {
let filler = async { let filler = async {
let mut interval = tokio::time::interval(INACTIVITY_TIMEOUT); let mut interval = tokio::time::interval(INACTIVITY_TIMEOUT);
tokio::time::sleep(INACTIVITY_TIMEOUT).await; tokio::time::sleep(INACTIVITY_TIMEOUT).await;
let mut iteration = 0;
loop { loop {
interval.tick().await; interval.tick().await;
let mut found = 0;
for bucket in self.dht.routing_table.read().iter_buckets() { for bucket in self.dht.routing_table.read().iter_buckets() {
if bucket.leaf.last_refreshed.elapsed() < INACTIVITY_TIMEOUT { if bucket.leaf.last_refreshed.elapsed() < INACTIVITY_TIMEOUT {
continue; continue;
} }
found += 1;
let random_id = bucket.random_within(); let random_id = bucket.random_within();
tx.send(random_id).unwrap(); tx.send(random_id).unwrap();
} }
trace!("iteration {}, refreshing {} buckets", iteration, found);
iteration += 1;
} }
}; };
@ -851,15 +842,36 @@ impl DhtWorker {
} }
} }
async fn pinger(&self, mut rx: UnboundedReceiver<(Id20, SocketAddr)>) -> anyhow::Result<()> { async fn pinger(&self) -> anyhow::Result<()> {
let mut futs = FuturesUnordered::new(); let mut futs = FuturesUnordered::new();
let mut interval = tokio::time::interval(INACTIVITY_TIMEOUT / 4);
let (tx, mut rx) = unbounded_channel();
let looper = async {
let mut iteration = 0;
loop {
interval.tick().await;
let mut found = 0;
for node in self.dht.routing_table.read().iter() {
if matches!(
node.status(),
NodeStatus::Questionable | NodeStatus::Unknown
) {
found += 1;
tx.send((node.id(), node.addr())).unwrap();
}
}
trace!("iteration {}, pinging {} nodes", iteration, found);
iteration += 1;
}
};
tokio::pin!(looper);
loop { loop {
tokio::select! { tokio::select! {
_ = &mut looper => {},
r = rx.recv() => { r = rx.recv() => {
let (id, addr) = match r { let (id, addr) = r.unwrap();
Some(r) => r,
None => return Ok(()),
};
futs.push(async move { futs.push(async move {
self.dht.routing_table.write().mark_outgoing_request(&id); self.dht.routing_table.write().mark_outgoing_request(&id);
match self.dht.request(Request::Ping, addr).await { match self.dht.request(Request::Ping, addr).await {
@ -944,7 +956,6 @@ impl DhtWorker {
async fn start( async fn start(
self, self,
in_rx: UnboundedReceiver<WorkerSendRequest>, in_rx: UnboundedReceiver<WorkerSendRequest>,
ping_rx: UnboundedReceiver<(Id20, SocketAddr)>,
bootstrap_addrs: &[String], bootstrap_addrs: &[String],
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let (out_tx, mut out_rx) = channel(1); let (out_tx, mut out_rx) = channel(1);
@ -970,8 +981,10 @@ impl DhtWorker {
} }
.instrument(debug_span!("dht_responese_reader")); .instrument(debug_span!("dht_responese_reader"));
let pinger = self.pinger(ping_rx); let pinger = self.pinger().instrument(error_span!("pinger"));
let bucket_refresher = self.bucket_refresher(); let bucket_refresher = self
.bucket_refresher()
.instrument(error_span!("bucket_refresher"));
tokio::pin!(framer); tokio::pin!(framer);
tokio::pin!(bootstrap); tokio::pin!(bootstrap);
@ -1034,11 +1047,9 @@ impl DhtState {
.unwrap_or_else(|| crate::DHT_BOOTSTRAP.iter().map(|v| v.to_string()).collect()); .unwrap_or_else(|| crate::DHT_BOOTSTRAP.iter().map(|v| v.to_string()).collect());
let (in_tx, in_rx) = unbounded_channel(); let (in_tx, in_rx) = unbounded_channel();
let (ping_tx, ping_rx) = unbounded_channel();
let state = Arc::new(Self::new_internal( let state = Arc::new(Self::new_internal(
peer_id, peer_id,
in_tx, in_tx,
ping_tx,
config.routing_table, config.routing_table,
listen_addr, listen_addr,
)); ));
@ -1047,7 +1058,7 @@ impl DhtState {
let state = state.clone(); let state = state.clone();
async move { async move {
let worker = DhtWorker { socket, dht: state }; let worker = DhtWorker { socket, dht: state };
worker.start(in_rx, ping_rx, &bootstrap_addrs).await?; worker.start(in_rx, &bootstrap_addrs).await?;
Ok(()) Ok(())
} }
}); });

View file

@ -348,15 +348,9 @@ impl BucketTree {
} }
} }
pub fn add_node( pub fn add_node(&mut self, self_id: &Id20, id: Id20, addr: SocketAddr) -> InsertResult {
&mut self,
self_id: &Id20,
id: Id20,
addr: SocketAddr,
on_questionable_node: impl FnMut(Id20, SocketAddr) -> bool,
) -> InsertResult {
let idx = self.get_leaf(&id); let idx = self.get_leaf(&id);
self.insert_into_leaf(idx, self_id, id, addr, on_questionable_node) self.insert_into_leaf(idx, self_id, id, addr)
} }
fn insert_into_leaf( fn insert_into_leaf(
&mut self, &mut self,
@ -364,7 +358,6 @@ impl BucketTree {
self_id: &Id20, self_id: &Id20,
id: Id20, id: Id20,
addr: SocketAddr, addr: SocketAddr,
mut on_questionable_node: impl FnMut(Id20, SocketAddr) -> bool,
) -> InsertResult { ) -> InsertResult {
// The loop here is for this case: // The loop here is for this case:
// in case we split a node into two, and it degenerates into all the leaves // in case we split a node into two, and it degenerates into all the leaves
@ -399,17 +392,6 @@ impl BucketTree {
return InsertResult::Added; return InsertResult::Added;
} }
// Ping first questionable node
if let Some(questionable_node) = nodes
.nodes
.iter_mut()
.find(|r| matches!(r.status(), NodeStatus::Questionable))
{
if on_questionable_node(questionable_node.id, questionable_node.addr) {
questionable_node.mark_outgoing_request();
}
}
// Try replace a bad node // Try replace a bad node
if let Some(bad_node) = nodes if let Some(bad_node) = nodes
.nodes .nodes
@ -633,15 +615,12 @@ impl RoutingTable {
self.buckets.iter_leaves() self.buckets.iter_leaves()
} }
pub fn add_node( pub fn iter(&self) -> impl Iterator<Item = &'_ RoutingTableNode> + '_ {
&mut self, self.buckets.iter()
id: Id20, }
addr: SocketAddr,
on_questionable_node: impl FnMut(Id20, SocketAddr) -> bool, pub fn add_node(&mut self, id: Id20, addr: SocketAddr) -> InsertResult {
) -> InsertResult { let res = self.buckets.add_node(&self.id, id, addr);
let res = self
.buckets
.add_node(&self.id, id, addr, on_questionable_node);
let replaced = match &res { let replaced = match &res {
InsertResult::WasExisting => false, InsertResult::WasExisting => false,
InsertResult::ReplacedBad(..) => true, InsertResult::ReplacedBad(..) => true,
@ -782,7 +761,7 @@ mod tests {
for _ in 0..length.unwrap_or(16536) { for _ in 0..length.unwrap_or(16536) {
let other_id = random_id_20(); let other_id = random_id_20();
let addr = generate_socket_addr(); let addr = generate_socket_addr();
rtable.add_node(other_id, addr, |_, _| false); rtable.add_node(other_id, addr);
} }
rtable rtable
} }