use crate::bgp_client::BGPClient;
pub const SECS_PER_SCAN_RESULTS: u64 = 15;
+const MAX_CONNS_PER_SEC_PER_STATUS: u64 = 30;
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub enum AddressState {
last_good: Instant, // Ignored unless state is Good or WasGood
last_services: u64,
state: AddressState,
+ queued: bool,
}
/// Essentially SocketAddr but without a traffic class or scope
}
struct Nodes {
- good_node_services: Vec<HashSet<SockAddr>>,
+ good_node_services: [HashSet<SockAddr>; 64],
nodes_to_state: HashMap<SockAddr, Node>,
state_next_scan: Vec<Vec<(Instant, SockAddr)>>,
}
struct NodesMutRef<'a> {
- good_node_services: &'a mut Vec<HashSet<SockAddr>>,
+ good_node_services: &'a mut [HashSet<SockAddr>; 64],
nodes_to_state: &'a mut HashMap<SockAddr, Node>,
state_next_scan: &'a mut Vec<Vec<(Instant, SockAddr)>>,
}
for _ in 0..AddressState::get_count() {
state_vecs.push(Vec::new());
}
- let mut good_node_services = Vec::with_capacity(64);
- for _ in 0..64 {
- good_node_services.push(HashSet::new());
- }
+ let good_node_services = [HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new()];
Nodes {
good_node_services,
nodes_to_state: HashMap::new(),
last_services,
last_update: Instant::now(),
last_good: Instant::now(),
+ queued: true,
};
if node.state == AddressState::Good {
for i in 0..64 {
last_services: 0,
last_update: cur_time,
last_good: cur_time,
+ queued: true,
});
nodes.state_next_scan[AddressState::Untested.to_num() as usize].push((cur_time, addr.into()));
res += 1;
last_services: 0,
last_update: now,
last_good: now,
+ queued: false,
});
let ret = state_ref.state;
if (state_ref.state == AddressState::Good || state_ref.state == AddressState::WasGood)
}
}
state_ref.last_services = 0;
- nodes.state_next_scan[AddressState::WasGood.to_num() as usize].push((now, addr));
+ if !state_ref.queued {
+ nodes.state_next_scan[AddressState::WasGood.to_num() as usize].push((now, addr));
+ state_ref.queued = true;
+ }
} else {
state_ref.state = state;
if state == AddressState::Good {
state_ref.last_services = services;
state_ref.last_good = now;
}
- nodes.state_next_scan[state.to_num() as usize].push((now, addr));
+ if !state_ref.queued {
+ nodes.state_next_scan[state.to_num() as usize].push((now, addr));
+ state_ref.queued = true;
+ }
}
state_ref.last_update = now;
ret
let mut dns_buff = String::new();
{
let mut rng = thread_rng();
- for i in &[1u64, 4, 5, 8, 9, 12, 13, 1024, 1025, 1028, 1029, 1032, 1033, 1036, 1037] {
+ for i in &[ 0b00000000001u64,
+ 0b00000000100,
+ 0b00000000101,
+ 0b00000001000,
+ 0b00000001001,
+ 0b00000001100,
+ 0b00000001101,
+ 0b00001001001,
+ 0b10000000000,
+ 0b10000000001,
+ 0b10000000100,
+ 0b10000000101,
+ 0b10000001000,
+ 0b10000001001,
+ 0b10000001100,
+ 0b10000001101,
+ 0b10001001000] {
+ // ^ NODE_NETWORK_LIIMTED
+ //COMPACT_FILTERS ^ ^ NODE_BLOOM
+ // NODE_WITNESS ^ ^ NODE_NETWORK
+ // We support all combos of NETWORK, NETWORK_LIMITED, BLOOM, and WITNESS
+ // We support COMPACT_FILTERS with WITNESS and NETWORK or NETWORK_LIIMTED.
let mut tor_set: Vec<Ipv6Addr> = Vec::new();
let mut v6_set: Vec<Ipv6Addr> = Vec::new();
let mut v4_set: Vec<Ipv4Addr> = Vec::new();
let cur_time = Instant::now();
{
- let mut nodes = self.nodes.write().unwrap();
+ let mut nodes_lock = self.nodes.write().unwrap();
+ let nodes = nodes_lock.borrow_mut();
for (idx, state_nodes) in nodes.state_next_scan.iter_mut().enumerate() {
let rescan_interval = cmp::max(self.get_u64(U64Setting::RescanInterval(AddressState::from_num(idx as u8).unwrap())), 1);
let cmp_time = cur_time - Duration::from_secs(rescan_interval);
- let split_point = cmp::min(SECS_PER_SCAN_RESULTS * state_nodes.len() as u64 / rescan_interval,
+ let split_point = cmp::min(cmp::min(SECS_PER_SCAN_RESULTS * state_nodes.len() as u64 / rescan_interval,
+ SECS_PER_SCAN_RESULTS * MAX_CONNS_PER_SEC_PER_STATUS),
state_nodes.binary_search_by(|a| a.0.cmp(&cmp_time)).unwrap_or_else(|idx| idx) as u64);
let mut new_nodes = state_nodes.split_off(split_point as usize);
mem::swap(&mut new_nodes, state_nodes);
for (_, node) in new_nodes.drain(..) {
+ nodes.nodes_to_state.get_mut(&node).unwrap().queued = false;
res.push((&node).into());
}
}