use std::net::SocketAddr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::SyncSender;
use std::sync::Arc;
use std::thread::JoinHandle;
use std::time::Duration;
use crate::telemetry::TickTrace;
use crate::tracer::NodeMeta;
#[derive(Debug)]
pub(crate) struct AcceptorGuard {
shutdown: Arc<AtomicBool>,
wake_addr: SocketAddr,
acceptor_handle: Option<JoinHandle<()>>,
}
impl AcceptorGuard {
pub(crate) fn new(shutdown: Arc<AtomicBool>, bound_addr: SocketAddr, acceptor_handle: JoinHandle<()>) -> Self {
Self {
shutdown,
wake_addr: wake_addr_for(bound_addr),
acceptor_handle: Some(acceptor_handle),
}
}
}
impl Drop for AcceptorGuard {
fn drop(&mut self) {
self.shutdown.store(true, Ordering::Relaxed);
let _ = std::net::TcpStream::connect_timeout(&self.wake_addr, Duration::from_millis(500));
if let Some(handle) = self.acceptor_handle.take() {
let _ = handle.join();
}
}
}
fn wake_addr_for(addr: SocketAddr) -> SocketAddr {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
if !addr.ip().is_unspecified() {
return addr;
}
let loopback = match addr {
SocketAddr::V4(_) => IpAddr::V4(Ipv4Addr::LOCALHOST),
SocketAddr::V6(_) => IpAddr::V6(Ipv6Addr::LOCALHOST),
};
SocketAddr::new(loopback, addr.port())
}
#[derive(Clone, Debug, Default)]
pub(crate) struct TelemetryState {
pub node_metas: Vec<NodeMeta>,
pub sender: Option<SyncSender<TickTrace>>,
pub acceptor_guard: Option<Arc<AcceptorGuard>>,
pub dropped_traces: u64,
pub trace_buffer: TickTrace,
}
impl TelemetryState {
pub fn new(node_metas: Vec<NodeMeta>) -> Self {
Self {
node_metas,
sender: None,
acceptor_guard: None,
dropped_traces: 0,
trace_buffer: TickTrace::default(),
}
}
}