refactor checkpoint

This commit is contained in:
John Smith
2022-04-16 11:18:54 -04:00
parent ddb74d993f
commit 71f7017235
23 changed files with 977 additions and 615 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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),
}
}

View File

@@ -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))?;

View File

@@ -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())
}
}