bee_protocol_types/
peer.rs1use std::{
7 sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering},
8 time::{SystemTime, UNIX_EPOCH},
9};
10
11use bee_block::payload::milestone::MilestoneIndex;
12use bee_gossip::{Multiaddr, PeerId, PeerInfo, PeerRelation};
13
14use crate::metrics::PeerMetrics;
15
16const SYNCED_THRESHOLD: u32 = 2;
17
18pub struct Peer {
20 id: PeerId,
21 info: PeerInfo,
22 connected: AtomicBool,
23 metrics: PeerMetrics,
24 solid_milestone_index: AtomicU32,
25 pruned_index: AtomicU32,
26 latest_milestone_index: AtomicU32,
27 connected_peers: AtomicU8,
28 synced_peers: AtomicU8,
29 heartbeat_sent_timestamp: AtomicU64,
30 heartbeat_received_timestamp: AtomicU64,
31}
32
33impl Peer {
34 pub fn new(id: PeerId, info: PeerInfo) -> Self {
36 Self {
37 id,
38 info,
39 connected: AtomicBool::new(false),
40 metrics: PeerMetrics::default(),
41 solid_milestone_index: AtomicU32::new(0),
42 pruned_index: AtomicU32::new(0),
43 latest_milestone_index: AtomicU32::new(0),
44 connected_peers: AtomicU8::new(0),
45 synced_peers: AtomicU8::new(0),
46 heartbeat_sent_timestamp: AtomicU64::new(0),
47 heartbeat_received_timestamp: AtomicU64::new(0),
48 }
49 }
50
51 pub fn id(&self) -> &PeerId {
53 &self.id
54 }
55
56 pub fn address(&self) -> &Multiaddr {
58 &self.info.address
59 }
60
61 pub fn alias(&self) -> &String {
63 &self.info.alias
64 }
65
66 pub fn relation(&self) -> PeerRelation {
68 self.info.relation
69 }
70
71 pub fn set_connected(&self, connected: bool) {
73 self.connected.store(connected, Ordering::Relaxed);
74 }
75
76 pub fn is_connected(&self) -> bool {
78 self.connected.load(Ordering::Relaxed)
79 }
80
81 pub fn metrics(&self) -> &PeerMetrics {
83 &self.metrics
84 }
85
86 pub fn set_solid_milestone_index(&self, index: MilestoneIndex) {
88 self.solid_milestone_index.store(*index, Ordering::Relaxed);
89 }
90
91 pub fn solid_milestone_index(&self) -> MilestoneIndex {
93 self.solid_milestone_index.load(Ordering::Relaxed).into()
94 }
95
96 pub fn set_pruned_index(&self, index: MilestoneIndex) {
98 self.pruned_index.store(*index, Ordering::Relaxed);
99 }
100
101 pub fn pruned_index(&self) -> MilestoneIndex {
103 self.pruned_index.load(Ordering::Relaxed).into()
104 }
105
106 pub fn set_latest_milestone_index(&self, index: MilestoneIndex) {
108 self.latest_milestone_index.store(*index, Ordering::Relaxed);
109 }
110
111 pub fn latest_milestone_index(&self) -> MilestoneIndex {
113 self.latest_milestone_index.load(Ordering::Relaxed).into()
114 }
115
116 pub fn set_connected_peers(&self, connected_peers: u8) {
118 self.connected_peers.store(connected_peers, Ordering::Relaxed);
119 }
120
121 pub fn connected_peers(&self) -> u8 {
123 self.connected_peers.load(Ordering::Relaxed)
124 }
125
126 pub fn set_synced_peers(&self, synced_peers: u8) {
128 self.synced_peers.store(synced_peers, Ordering::Relaxed);
129 }
130
131 pub fn synced_peers(&self) -> u8 {
133 self.synced_peers.load(Ordering::Relaxed)
134 }
135
136 pub fn set_heartbeat_sent_timestamp(&self) {
138 self.heartbeat_sent_timestamp.store(
139 SystemTime::now()
140 .duration_since(UNIX_EPOCH)
141 .expect("Clock may have gone backwards")
142 .as_millis() as u64,
143 Ordering::Relaxed,
144 );
145 }
146
147 pub fn heartbeat_sent_timestamp(&self) -> u64 {
149 self.heartbeat_sent_timestamp.load(Ordering::Relaxed)
150 }
151
152 pub fn set_heartbeat_received_timestamp(&self) {
154 self.heartbeat_received_timestamp.store(
155 SystemTime::now()
156 .duration_since(UNIX_EPOCH)
157 .expect("Clock may have gone backwards")
158 .as_millis() as u64,
159 Ordering::Relaxed,
160 );
161 }
162
163 pub fn heartbeat_received_timestamp(&self) -> u64 {
165 self.heartbeat_received_timestamp.load(Ordering::Relaxed)
166 }
167
168 pub fn is_synced(&self) -> bool {
170 self.is_synced_threshold(SYNCED_THRESHOLD)
171 }
172
173 pub fn is_synced_threshold(&self, threshold: u32) -> bool {
175 *self.solid_milestone_index() >= (*self.latest_milestone_index()).saturating_sub(threshold)
176 }
177
178 pub fn has_data(&self, index: MilestoneIndex) -> bool {
180 index > self.pruned_index() && index <= self.solid_milestone_index() + MilestoneIndex(1)
182 }
183
184 pub fn maybe_has_data(&self, index: MilestoneIndex) -> bool {
186 index > self.pruned_index() && index <= self.latest_milestone_index() + MilestoneIndex(1)
188 }
189}