rings_core/dht/finger/
mod.rs1#![deny(missing_docs)]
4
5use serde::Deserialize;
6use serde::Serialize;
7
8use crate::dht::did::BiasId;
9use crate::dht::Did;
10
11pub const DEFAULT_FINGER_TABLE_SIZE: usize = 160;
13
14#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct FingerTable {
18 did: Did,
19 size: usize,
20 finger: Vec<Option<Did>>,
21 pub(super) fix_finger_index: usize,
22}
23
24impl PartialEq for FingerTable {
25 fn eq(&self, other: &Self) -> bool {
26 self.did == other.did && self.size == other.size && self.finger == other.finger
27 }
28}
29
30impl Eq for FingerTable {}
31
32impl FingerTable {
33 pub fn new(did: Did, size: usize) -> Self {
40 let size = size.min(DEFAULT_FINGER_TABLE_SIZE);
41 Self {
42 did,
43 size,
44 finger: vec![None; size],
45 fix_finger_index: 0,
46 }
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.len() == 0
52 }
53
54 pub fn first(&self) -> Option<Did> {
56 self.finger.iter().flatten().next().copied()
57 }
58
59 pub fn get(&self, index: usize) -> Option<Did> {
61 self.finger.get(index).copied().flatten()
62 }
63
64 fn write_slot(&mut self, index: usize, did: Option<Did>) {
65 if let Some(slot) = self.finger.get_mut(index) {
66 *slot = did;
67 }
68 }
69
70 pub fn set(&mut self, index: usize, did: Did) {
72 tracing::debug!("set finger table index: {} did: {}", index, did);
73 if index >= self.finger.len() {
74 tracing::error!("set finger index out of range, index: {}", index);
75 return;
76 }
77 if did == self.did {
78 tracing::trace!("set finger table with self did, ignore it");
79 return;
80 }
81 self.write_slot(index, Some(did));
82 }
83
84 pub fn set_fix(&mut self, did: Did) {
86 let index = self.fix_finger_index;
87 self.set(index, did)
88 }
89
90 pub fn remove(&mut self, did: Did) {
92 self.finger = crate::dht::topology::remove_finger_peer(&self.finger, did);
93 }
94
95 pub fn join(&mut self, did: Did) {
97 let observer = self.did;
98 let bias = did.bias(observer);
99
100 for k in 0..self.size {
101 let pos = Did::power_of_two(k);
102
103 if bias.pos() < pos {
104 continue;
105 }
106
107 if let Some(v) = self.finger.get(k).copied().flatten() {
108 if BiasId::cmp_from_observer(observer, did, v) == std::cmp::Ordering::Greater {
109 continue;
110 }
111 }
112
113 self.write_slot(k, Some(did));
114 }
115 }
116
117 pub fn contains(&self, v: Option<Did>) -> bool {
119 self.finger.contains(&v)
120 }
121
122 pub fn closest_predecessor(&self, did: Did) -> Did {
124 let observer = self.did;
125
126 for i in (0..self.size).rev() {
127 if let Some(v) = self.finger.get(i).copied().flatten() {
128 if BiasId::cmp_from_observer(observer, v, did) == std::cmp::Ordering::Less {
129 return v;
130 }
131 }
132 }
133
134 self.did
135 }
136
137 pub fn len(&self) -> usize {
139 self.finger.iter().flatten().count()
140 }
141
142 pub fn slot_count(&self) -> usize {
144 self.size
145 }
146
147 pub fn fix_finger_index(&self) -> usize {
149 self.fix_finger_index
150 }
151
152 pub fn list(&self) -> &Vec<Option<Did>> {
154 &self.finger
155 }
156
157 pub(crate) fn replace_state(&mut self, fingers: &[Option<Did>], fix_finger_index: usize) {
163 self.finger = fingers.iter().copied().take(self.size).collect();
164 self.finger.resize(self.size, None);
165 self.fix_finger_index = if self.size == 0 {
166 0
167 } else {
168 fix_finger_index % self.size
169 };
170 }
171
172 #[cfg(test)]
174 pub fn reset_finger(&mut self) {
175 self.finger = vec![None; self.size]
176 }
177
178 #[cfg(test)]
180 pub fn clone_finger(self) -> Vec<Option<Did>> {
181 self.finger
182 }
183}
184
185#[cfg(test)]
186mod test_finger;