refactor checkpoint
This commit is contained in:
@@ -35,9 +35,10 @@ pub enum BucketEntryState {
|
||||
pub struct BucketEntry {
|
||||
pub(super) ref_count: u32,
|
||||
min_max_version: Option<(u8, u8)>,
|
||||
seen_our_dial_info: bool,
|
||||
seen_our_node_info: bool,
|
||||
last_connection: Option<(ConnectionDescriptor, u64)>,
|
||||
node_info: NodeInfo,
|
||||
local_node_info: LocalNodeInfo,
|
||||
peer_stats: PeerStats,
|
||||
latency_stats_accounting: LatencyStatsAccounting,
|
||||
transfer_stats_accounting: TransferStatsAccounting,
|
||||
@@ -49,9 +50,10 @@ impl BucketEntry {
|
||||
Self {
|
||||
ref_count: 0,
|
||||
min_max_version: None,
|
||||
seen_our_dial_info: false,
|
||||
seen_our_node_info: false,
|
||||
last_connection: None,
|
||||
node_info: NodeInfo::default(),
|
||||
local_node_info: LocalNodeInfo::default(),
|
||||
latency_stats_accounting: LatencyStatsAccounting::new(),
|
||||
transfer_stats_accounting: TransferStatsAccounting::new(),
|
||||
peer_stats: PeerStats {
|
||||
@@ -108,34 +110,20 @@ impl BucketEntry {
|
||||
pub fn update_node_info(&mut self, node_info: NodeInfo) {
|
||||
self.node_info = node_info
|
||||
}
|
||||
pub fn update_local_node_info(&mut self, local_node_info: LocalNodeInfo) {
|
||||
self.local_node_info = local_node_info
|
||||
}
|
||||
|
||||
pub fn node_info(&self) -> &NodeInfo {
|
||||
&self.node_info
|
||||
}
|
||||
|
||||
pub fn first_filtered_node_info<F>(&self, filter: F) -> Option<NodeInfo>
|
||||
where
|
||||
F: Fn(&DialInfo) -> bool,
|
||||
{
|
||||
let out = self.node_info.first_filtered(filter);
|
||||
if out.dial_infos.is_empty() && out.relay_dial_infos.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(out)
|
||||
}
|
||||
pub fn local_node_info(&self) -> &LocalNodeInfo {
|
||||
&self.local_node_info
|
||||
}
|
||||
|
||||
pub fn all_filtered_node_info<F>(&self, filter: F) -> NodeInfo
|
||||
where
|
||||
F: Fn(&DialInfo) -> bool,
|
||||
{
|
||||
self.node_info.all_filtered(filter)
|
||||
}
|
||||
|
||||
pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo {
|
||||
pub fn peer_info(&self, key: DHTKey) -> PeerInfo {
|
||||
PeerInfo {
|
||||
node_id: NodeId::new(key),
|
||||
node_info: self.all_filtered_node_info(|di| di.matches_peer_scope(scope)),
|
||||
node_info: self.node_info.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,12 +161,12 @@ impl BucketEntry {
|
||||
self.peer_stats.status = Some(status);
|
||||
}
|
||||
|
||||
pub fn set_seen_our_dial_info(&mut self, seen: bool) {
|
||||
self.seen_our_dial_info = seen;
|
||||
pub fn set_seen_our_node_info(&mut self, seen: bool) {
|
||||
self.seen_our_node_info = seen;
|
||||
}
|
||||
|
||||
pub fn has_seen_our_dial_info(&self) -> bool {
|
||||
self.seen_our_dial_info
|
||||
pub fn has_seen_our_node_info(&self) -> bool {
|
||||
self.seen_our_node_info
|
||||
}
|
||||
|
||||
///// stats methods
|
||||
|
@@ -23,15 +23,15 @@ impl RoutingTable {
|
||||
out
|
||||
}
|
||||
pub fn debug_info_dialinfo(&self) -> String {
|
||||
let ldis = self.local_dial_info_details();
|
||||
let gdis = self.global_dial_info_details();
|
||||
let ldis = self.interface_dial_info_details();
|
||||
let gdis = self.public_dial_info_details();
|
||||
let mut out = String::new();
|
||||
|
||||
out += "Local Dial Info Details:\n";
|
||||
out += "Interface Dial Info Details:\n";
|
||||
for (n, ldi) in ldis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
||||
}
|
||||
out += "Global Dial Info Details:\n";
|
||||
out += "Public Dial Info Details:\n";
|
||||
for (n, gdi) in gdis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@ impl RoutingTable {
|
||||
// Returns noderefs are are scoped to that address type only
|
||||
pub fn find_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
|
||||
let dial_info_filter1 = dial_info_filter.clone();
|
||||
let dial_info_filter2 = dial_info_filter.clone();
|
||||
self.find_fastest_nodes(
|
||||
// filter
|
||||
Some(Box::new(
|
||||
@@ -21,50 +20,53 @@ impl RoutingTable {
|
||||
.1
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.first_filtered_node_info(|di| di.matches_filter(&dial_info_filter1))
|
||||
.node_info()
|
||||
.first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter1))
|
||||
.is_some()
|
||||
},
|
||||
)),
|
||||
// transform
|
||||
|e| {
|
||||
NodeRef::new_filtered(
|
||||
self.clone(),
|
||||
*e.0,
|
||||
e.1.as_mut().unwrap(),
|
||||
dial_info_filter2.clone(),
|
||||
)
|
||||
},
|
||||
|e| NodeRef::new(self.clone(), *e.0, e.1.as_mut().unwrap()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo {
|
||||
let filter = DialInfoFilter::scoped(scope);
|
||||
pub fn get_own_peer_info(&self) -> PeerInfo {
|
||||
let netman = self.network_manager();
|
||||
let enable_local_peer_scope = netman.config().get().network.enable_local_peer_scope;
|
||||
let relay_node = netman.relay_node();
|
||||
PeerInfo {
|
||||
node_id: NodeId::new(self.node_id()),
|
||||
node_info: NodeInfo {
|
||||
network_class: netman.get_network_class().unwrap_or(NetworkClass::Invalid),
|
||||
dial_infos: self
|
||||
.all_filtered_dial_info_details(&filter)
|
||||
.iter()
|
||||
.map(|did| did.dial_info.clone())
|
||||
.collect(),
|
||||
relay_dial_infos: relay_node
|
||||
.map(|rn| rn.node_info().dial_infos)
|
||||
.unwrap_or_default(),
|
||||
outbound_protocols: netman.get_protocol_config().unwrap_or_default().outbound,
|
||||
dial_info_list: if !enable_local_peer_scope {
|
||||
self.public_dial_info_details()
|
||||
.iter()
|
||||
.map(|did| did.dial_info.clone())
|
||||
.collect()
|
||||
} else {
|
||||
self.public_dial_info_details()
|
||||
.iter()
|
||||
.map(|did| did.dial_info.clone())
|
||||
.chain(
|
||||
self.interface_dial_info_details()
|
||||
.iter()
|
||||
.map(|did| did.dial_info.clone()),
|
||||
)
|
||||
.collect()
|
||||
},
|
||||
relay_peer_info: relay_node.map(|rn| Box::new(rn.peer_info())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_to_peer_info(
|
||||
kv: &mut (&DHTKey, Option<&mut BucketEntry>),
|
||||
scope: PeerScope,
|
||||
own_peer_info: &PeerInfo,
|
||||
) -> PeerInfo {
|
||||
match &kv.1 {
|
||||
None => own_peer_info.clone(),
|
||||
Some(entry) => entry.get_peer_info(*kv.0, scope),
|
||||
Some(entry) => entry.peer_info(*kv.0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,8 @@ struct RoutingTableInner {
|
||||
node_id: DHTKey,
|
||||
node_id_secret: DHTKeySecret,
|
||||
buckets: Vec<Bucket>,
|
||||
dial_info_details: Vec<DialInfoDetail>,
|
||||
public_dial_info_details: Vec<DialInfoDetail>,
|
||||
interface_dial_info_details: Vec<DialInfoDetail>,
|
||||
bucket_entry_count: usize,
|
||||
|
||||
// Waiters
|
||||
@@ -89,7 +90,8 @@ impl RoutingTable {
|
||||
node_id: DHTKey::default(),
|
||||
node_id_secret: DHTKeySecret::default(),
|
||||
buckets: Vec::new(),
|
||||
dial_info_details: Vec::new(),
|
||||
public_dial_info_details: Vec::new(),
|
||||
interface_dial_info_details: Vec::new(),
|
||||
bucket_entry_count: 0,
|
||||
eventual_changed_dial_info: Eventual::new(),
|
||||
self_latency_stats_accounting: LatencyStatsAccounting::new(),
|
||||
@@ -163,40 +165,42 @@ impl RoutingTable {
|
||||
self.inner.lock().node_id_secret
|
||||
}
|
||||
|
||||
pub fn has_local_dial_info(&self) -> bool {
|
||||
self.first_filtered_dial_info_detail(&DialInfoFilter::local())
|
||||
.is_some()
|
||||
pub fn has_interface_dial_info(&self) -> bool {
|
||||
!self.inner.lock().interface_dial_info_details.is_empty()
|
||||
}
|
||||
|
||||
pub fn has_global_dial_info(&self) -> bool {
|
||||
self.first_filtered_dial_info_detail(&DialInfoFilter::global())
|
||||
.is_some()
|
||||
pub fn has_public_dial_info(&self) -> bool {
|
||||
!self.inner.lock().public_dial_info_details.is_empty()
|
||||
}
|
||||
|
||||
pub fn global_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||
self.all_filtered_dial_info_details(&DialInfoFilter::global())
|
||||
pub fn public_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||
self.inner.lock().public_dial_info_details.clone()
|
||||
}
|
||||
|
||||
pub fn local_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||
self.all_filtered_dial_info_details(&DialInfoFilter::local())
|
||||
pub fn interface_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||
self.inner.lock().interface_dial_info_details.clone()
|
||||
}
|
||||
|
||||
pub fn first_filtered_dial_info_detail(
|
||||
pub fn first_public_filtered_dial_info_detail(
|
||||
&self,
|
||||
filter: &DialInfoFilter,
|
||||
) -> Option<DialInfoDetail> {
|
||||
let inner = self.inner.lock();
|
||||
for did in &inner.dial_info_details {
|
||||
for did in &inner.public_dial_info_details {
|
||||
if did.matches_filter(filter) {
|
||||
return Some(did.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn all_filtered_dial_info_details(&self, filter: &DialInfoFilter) -> Vec<DialInfoDetail> {
|
||||
|
||||
pub fn all_public_filtered_dial_info_details(
|
||||
&self,
|
||||
filter: &DialInfoFilter,
|
||||
) -> Vec<DialInfoDetail> {
|
||||
let inner = self.inner.lock();
|
||||
let mut ret = Vec::new();
|
||||
for did in &inner.dial_info_details {
|
||||
for did in &inner.public_dial_info_details {
|
||||
if did.matches_filter(filter) {
|
||||
ret.push(did.clone());
|
||||
}
|
||||
@@ -204,16 +208,48 @@ impl RoutingTable {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn register_dial_info(
|
||||
pub fn first_interface_filtered_dial_info_detail(
|
||||
&self,
|
||||
filter: &DialInfoFilter,
|
||||
) -> Option<DialInfoDetail> {
|
||||
let inner = self.inner.lock();
|
||||
for did in &inner.interface_dial_info_details {
|
||||
if did.matches_filter(filter) {
|
||||
return Some(did.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn all_interface_filtered_dial_info_details(
|
||||
&self,
|
||||
filter: &DialInfoFilter,
|
||||
) -> Vec<DialInfoDetail> {
|
||||
let inner = self.inner.lock();
|
||||
let mut ret = Vec::new();
|
||||
for did in &inner.interface_dial_info_details {
|
||||
if did.matches_filter(filter) {
|
||||
ret.push(did.clone());
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn register_public_dial_info(
|
||||
&self,
|
||||
dial_info: DialInfo,
|
||||
origin: DialInfoOrigin,
|
||||
network_class: Option<NetworkClass>,
|
||||
) {
|
||||
let timestamp = get_timestamp();
|
||||
let enable_local_peer_scope = {
|
||||
let c = self.network_manager().config().get();
|
||||
c.network.enable_local_peer_scope
|
||||
};
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
|
||||
inner.dial_info_details.push(DialInfoDetail {
|
||||
inner.public_dial_info_details.push(DialInfoDetail {
|
||||
dial_info: dial_info.clone(),
|
||||
origin,
|
||||
network_class,
|
||||
@@ -222,18 +258,11 @@ impl RoutingTable {
|
||||
|
||||
// Re-sort dial info to endure preference ordering
|
||||
inner
|
||||
.dial_info_details
|
||||
.public_dial_info_details
|
||||
.sort_by(|a, b| a.dial_info.cmp(&b.dial_info));
|
||||
|
||||
info!(
|
||||
"{}Dial Info: {}",
|
||||
if dial_info.is_local() {
|
||||
"Local "
|
||||
} else if dial_info.is_global() {
|
||||
"Global "
|
||||
} else {
|
||||
"Other "
|
||||
},
|
||||
"Public Dial Info: {}",
|
||||
NodeDialInfo {
|
||||
node_id: NodeId::new(inner.node_id),
|
||||
dial_info
|
||||
@@ -246,9 +275,44 @@ impl RoutingTable {
|
||||
Self::trigger_changed_dial_info(&mut *inner);
|
||||
}
|
||||
|
||||
pub fn register_interface_dial_info(&self, dial_info: DialInfo, origin: DialInfoOrigin) {
|
||||
let timestamp = get_timestamp();
|
||||
let enable_local_peer_scope = {
|
||||
let c = self.network_manager().config().get();
|
||||
c.network.enable_local_peer_scope
|
||||
};
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
|
||||
inner.interface_dial_info_details.push(DialInfoDetail {
|
||||
dial_info: dial_info.clone(),
|
||||
origin,
|
||||
network_class: None,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
// Re-sort dial info to endure preference ordering
|
||||
inner
|
||||
.interface_dial_info_details
|
||||
.sort_by(|a, b| a.dial_info.cmp(&b.dial_info));
|
||||
|
||||
info!(
|
||||
"Interface Dial Info: {}",
|
||||
NodeDialInfo {
|
||||
node_id: NodeId::new(inner.node_id),
|
||||
dial_info
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
debug!(" Origin: {:?}", origin);
|
||||
|
||||
Self::trigger_changed_dial_info(&mut *inner);
|
||||
}
|
||||
|
||||
pub fn clear_dial_info_details(&self) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dial_info_details.clear();
|
||||
inner.public_dial_info_details.clear();
|
||||
inner.interface_dial_info_details.clear();
|
||||
Self::trigger_changed_dial_info(&mut *inner);
|
||||
}
|
||||
|
||||
@@ -262,10 +326,10 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
fn trigger_changed_dial_info(inner: &mut RoutingTableInner) {
|
||||
// Clear 'seen dial info' bits on routing table entries so we know to ping them
|
||||
// Clear 'seen node info' bits on routing table entries so we know to ping them
|
||||
for b in &mut inner.buckets {
|
||||
for e in b.entries_mut() {
|
||||
e.1.set_seen_our_dial_info(false);
|
||||
e.1.set_seen_our_node_info(false);
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -608,9 +672,10 @@ impl RoutingTable {
|
||||
.register_node_with_node_info(
|
||||
k,
|
||||
NodeInfo {
|
||||
network_class: NetworkClass::Server,
|
||||
dial_infos: v,
|
||||
relay_dial_infos: Default::default(),
|
||||
network_class: NetworkClass::Server, // Bootstraps are always full servers
|
||||
outbound_protocols: ProtocolSet::default(), // Bootstraps do not participate in relaying and will not make outbound requests
|
||||
dial_info_list: v, // Dial info is as specified in the bootstrap list
|
||||
relay_peer_info: None, // Bootstraps never require a relay themselves
|
||||
},
|
||||
)
|
||||
.map_err(logthru_rtab!("Couldn't add bootstrap node: {}", k))?;
|
||||
|
@@ -5,7 +5,6 @@ use alloc::fmt;
|
||||
pub struct NodeRef {
|
||||
routing_table: RoutingTable,
|
||||
node_id: DHTKey,
|
||||
dial_info_filter: DialInfoFilter,
|
||||
}
|
||||
|
||||
impl NodeRef {
|
||||
@@ -14,20 +13,6 @@ impl NodeRef {
|
||||
Self {
|
||||
routing_table,
|
||||
node_id: key,
|
||||
dial_info_filter: DialInfoFilter::default(),
|
||||
}
|
||||
}
|
||||
pub fn new_filtered(
|
||||
routing_table: RoutingTable,
|
||||
key: DHTKey,
|
||||
entry: &mut BucketEntry,
|
||||
dial_info_filter: DialInfoFilter,
|
||||
) -> Self {
|
||||
entry.ref_count += 1;
|
||||
Self {
|
||||
routing_table,
|
||||
node_id: key,
|
||||
dial_info_filter,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +20,6 @@ impl NodeRef {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn dial_info_filter(&self) -> &DialInfoFilter {
|
||||
&self.dial_info_filter
|
||||
}
|
||||
|
||||
pub fn operate<T, F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut BucketEntry) -> T,
|
||||
@@ -46,52 +27,23 @@ impl NodeRef {
|
||||
self.routing_table.operate_on_bucket_entry(self.node_id, f)
|
||||
}
|
||||
|
||||
pub fn peer_info(&self) -> PeerInfo {
|
||||
self.operate(|e| e.peer_info(self.node_id()))
|
||||
}
|
||||
pub fn node_info(&self) -> NodeInfo {
|
||||
self.operate(|e| e.node_info().clone())
|
||||
}
|
||||
|
||||
pub fn has_dial_info(&self) -> bool {
|
||||
self.operate(|e| !e.node_info().dial_infos.is_empty())
|
||||
pub fn local_node_info(&self) -> LocalNodeInfo {
|
||||
self.operate(|e| e.local_node_info().clone())
|
||||
}
|
||||
|
||||
// Returns if this node has seen and acknowledged our node's dial info yet
|
||||
pub fn has_seen_our_dial_info(&self) -> bool {
|
||||
self.operate(|e| e.has_seen_our_dial_info())
|
||||
pub fn has_seen_our_node_info(&self) -> bool {
|
||||
self.operate(|e| e.has_seen_our_node_info())
|
||||
}
|
||||
pub fn set_seen_our_dial_info(&self) {
|
||||
self.operate(|e| e.set_seen_our_dial_info(true));
|
||||
}
|
||||
|
||||
// Returns the best node info to attempt a connection to this node
|
||||
pub fn best_node_info(&self) -> Option<NodeInfo> {
|
||||
let nm = self.routing_table.network_manager();
|
||||
let protocol_config = nm.get_protocol_config()?;
|
||||
self.operate(|e| {
|
||||
e.first_filtered_node_info(|di| {
|
||||
// Does it match the dial info filter
|
||||
if !di.matches_filter(&self.dial_info_filter) {
|
||||
return false;
|
||||
}
|
||||
// Filter out dial infos that don't match our protocol config
|
||||
// for outbound connections. This routine filters on 'connect' settings
|
||||
// to ensure we connect using only the protocols we have enabled.
|
||||
protocol_config.is_protocol_type_connect_enabled(di.protocol_type())
|
||||
})
|
||||
})
|
||||
pub fn set_seen_our_node_info(&self) {
|
||||
self.operate(|e| e.set_seen_our_node_info(true));
|
||||
}
|
||||
pub fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
||||
match self.operate(|e| e.last_connection()) {
|
||||
None => None,
|
||||
Some(c) => {
|
||||
if !c.matches_filter(&self.dial_info_filter) {
|
||||
return None;
|
||||
}
|
||||
// We don't filter this out by protocol config because if a connection
|
||||
// succeeded, it's allowed to persist and be used for communication
|
||||
// regardless of any other configuration
|
||||
Some(c)
|
||||
}
|
||||
}
|
||||
self.operate(|e| e.last_connection())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,18 +55,13 @@ impl Clone for NodeRef {
|
||||
Self {
|
||||
routing_table: self.routing_table.clone(),
|
||||
node_id: self.node_id,
|
||||
dial_info_filter: self.dial_info_filter.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for NodeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut out = self.node_id.encode();
|
||||
if !self.dial_info_filter.is_empty() {
|
||||
out += &format!("{:?}", self.dial_info_filter);
|
||||
}
|
||||
write!(f, "{}", out)
|
||||
write!(f, "{}", self.node_id.encode())
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user