1#![warn(missing_docs)]
4
5use derivative::Derivative;
6use serde::Deserialize;
7use serde::Serialize;
8
9use crate::dht::Did;
10
11pub const DEFAULT_FINGER_TABLE_SIZE: usize = 160;
13
14#[derive(Derivative, Clone, Debug, Serialize, Deserialize)]
17#[derivative(PartialEq)]
18pub struct FingerTable {
19 did: Did,
20 size: usize,
21 finger: Vec<Option<Did>>,
22 #[derivative(PartialEq = "ignore")]
23 pub(super) fix_finger_index: usize,
24}
25
26impl FingerTable {
27 pub fn new(did: Did, size: usize) -> Self {
34 let size = size.min(DEFAULT_FINGER_TABLE_SIZE);
35 Self {
36 did,
37 size,
38 finger: vec![None; size],
39 fix_finger_index: 0,
40 }
41 }
42
43 pub fn is_empty(&self) -> bool {
45 self.len() == 0
46 }
47
48 pub fn first(&self) -> Option<Did> {
50 self.finger.iter().flatten().next().copied()
51 }
52
53 pub fn get(&self, index: usize) -> Option<Did> {
55 self.finger.get(index).copied().flatten()
56 }
57
58 fn write_slot(&mut self, index: usize, did: Option<Did>) {
59 if let Some(slot) = self.finger.get_mut(index) {
60 *slot = did;
61 }
62 }
63
64 pub fn set(&mut self, index: usize, did: Did) {
66 tracing::debug!("set finger table index: {} did: {}", index, did);
67 if index >= self.finger.len() {
68 tracing::error!("set finger index out of range, index: {}", index);
69 return;
70 }
71 if did == self.did {
72 tracing::trace!("set finger table with self did, ignore it");
73 return;
74 }
75 self.write_slot(index, Some(did));
76 }
77
78 pub fn set_fix(&mut self, did: Did) {
80 let index = self.fix_finger_index;
81 self.set(index, did)
82 }
83
84 pub fn remove(&mut self, did: Did) {
86 let indexes: Vec<usize> = self
87 .finger
88 .iter()
89 .enumerate()
90 .filter(|(_, &x)| x == Some(did))
91 .map(|(id, _)| id)
92 .collect();
93
94 if let (Some(first_idx), Some(last_idx)) =
95 (indexes.first().copied(), indexes.last().copied())
96 {
97 let end_idx = last_idx + 1;
98
99 let fix_id = self.finger.get(end_idx).copied().flatten();
102
103 for idx in first_idx..end_idx {
104 self.write_slot(idx, fix_id);
105 }
106 }
107 }
108
109 pub fn join(&mut self, did: Did) {
111 let bias = did.bias(self.did);
112
113 for k in 0..self.size {
114 let pos = Did::power_of_two(k);
115
116 if bias.pos() < pos {
117 continue;
118 }
119
120 if let Some(v) = self.finger.get(k).copied().flatten() {
121 if bias > v.bias(self.did) {
122 continue;
123 }
124 }
125
126 self.write_slot(k, Some(did));
127 }
128 }
129
130 pub fn contains(&self, v: Option<Did>) -> bool {
132 self.finger.contains(&v)
133 }
134
135 pub fn closest_predecessor(&self, did: Did) -> Did {
137 let bias = did.bias(self.did);
138
139 for i in (0..self.size).rev() {
140 if let Some(v) = self.finger.get(i).copied().flatten() {
141 if v.bias(self.did) < bias {
142 return v;
143 }
144 }
145 }
146
147 self.did
148 }
149
150 pub fn len(&self) -> usize {
152 self.finger.iter().flatten().count()
153 }
154
155 pub fn slot_count(&self) -> usize {
157 self.size
158 }
159
160 pub fn fix_finger_index(&self) -> usize {
162 self.fix_finger_index
163 }
164
165 pub fn list(&self) -> &Vec<Option<Did>> {
167 &self.finger
168 }
169
170 pub(crate) fn replace_state(&mut self, fingers: &[Option<Did>], fix_finger_index: usize) {
176 self.finger = fingers.iter().copied().take(self.size).collect();
177 self.finger.resize(self.size, None);
178 self.fix_finger_index = if self.size == 0 {
179 0
180 } else {
181 fix_finger_index % self.size
182 };
183 }
184
185 #[cfg(test)]
187 pub fn reset_finger(&mut self) {
188 self.finger = vec![None; self.size]
189 }
190
191 #[cfg(test)]
193 pub fn clone_finger(self) -> Vec<Option<Did>> {
194 self.finger
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use super::*;
201 use crate::dht::tests::gen_ordered_dids;
202
203 #[test]
204 fn test_finger_table_size_bounds() {
205 let did = gen_ordered_dids(1)[0];
206
207 assert_eq!(
208 FingerTable::new(did, DEFAULT_FINGER_TABLE_SIZE + 1).slot_count(),
209 DEFAULT_FINGER_TABLE_SIZE
210 );
211 assert_eq!(FingerTable::new(did, 0).slot_count(), 0);
212 }
213
214 #[test]
215 fn test_finger_table_get_set_remove() {
216 let dids = gen_ordered_dids(5);
217
218 let mut table = FingerTable::new(dids[0], 3);
219 println!("check finger len");
220 assert_eq!(table.len(), 0);
221 assert_eq!(table.finger.len(), 3);
222 println!("check finger all items is none");
223 assert!(table.get(0).is_none(), "index 0 should be None");
224 assert!(table.get(1).is_none(), "index 1 should be None");
225 assert!(table.get(2).is_none(), "index 2 should be None");
226 assert!(table.get(3).is_none(), "index 3 should be None");
227
228 println!("set finger item");
229 let (id1, id2, id3, id4) = (dids[1], dids[2], dids[3], dids[4]);
230
231 table.set(0, id1);
232 assert_eq!(table.len(), 1);
233 assert_eq!(table.finger.len(), 3);
234
235 table.set(2, id3);
236 assert_eq!(table.len(), 2);
237 assert_eq!(table.finger.len(), 3);
238
239 assert!(
240 table.get(0) == Some(id1),
241 "expect value at index 0 is {:?}, got {:?}",
242 Some(id1),
243 table.get(0)
244 );
245 assert!(
246 table.get(1).is_none(),
247 "expect value at index 1 is None, got {:?}",
248 table.get(1)
249 );
250 assert!(
251 table.get(2) == Some(id3),
252 "expect value at index 2 is {:?}, got {:?}",
253 Some(id3),
254 table.get(2)
255 );
256
257 println!("set value out of index");
258 table.set(4, id4);
259 assert_eq!(table.len(), 2);
260 assert_eq!(table.finger.len(), 3);
261
262 println!("remove node from finger");
263 table.remove(id1);
264 assert_eq!(table.len(), 1);
265 assert_eq!(table.finger.len(), 3);
266 assert!(
267 table.get(0).is_none(),
268 "expect value at index 1 is None, got {:?}",
269 table.get(0)
270 );
271 assert!(
272 table.get(2) == Some(id3),
273 "expect value at index 2 is {:?}, got {:?}",
274 Some(id3),
275 table.get(2)
276 );
277
278 println!("remove node with auto fill");
279 table.set(0, id1);
280 table.set(1, id2);
281 assert!(
282 table.get(0) == Some(id1),
283 "expect value at index 0 is {:?}, got {:?}",
284 Some(id1),
285 table.get(0)
286 );
287 assert!(
288 table.get(1) == Some(id2),
289 "expect value at index 1 is {:?}, got {:?}",
290 Some(id2),
291 table.get(1)
292 );
293 assert!(
294 table.get(2) == Some(id3),
295 "expect value at index 2 is {:?}, got {:?}",
296 Some(id3),
297 table.get(2)
298 );
299
300 table.remove(id1);
301 assert_eq!(table.len(), 3);
302 assert_eq!(table.finger.len(), 3);
303 assert!(
304 table.get(0) == Some(id2),
305 "expect value at index 0 is {:?}, got {:?}",
306 id2,
307 table.get(0)
308 );
309 assert!(
310 table.get(1) == Some(id2),
311 "expect value at index 1 is {:?}, got {:?}",
312 Some(id2),
313 table.get(1),
314 );
315
316 println!("remove item not in fingers");
317 table.remove(id4);
318
319 println!("remove all items in fingers");
320 table.remove(id1);
321 assert_eq!(table.first(), Some(id2));
322
323 println!("check first item");
324 table.remove(id3);
325 assert_eq!(table.first(), Some(id2));
326
327 table.remove(id2);
328 assert_eq!(table.first(), None);
329 assert_eq!(table.len(), 0);
330 assert_eq!(table.finger.len(), 3);
331 }
332
333 #[test]
334 fn test_finger_table_remove_then_fill() {
335 let dids = gen_ordered_dids(6);
336 let (did1, did2, did3, did4, did5) = (dids[1], dids[2], dids[3], dids[4], dids[5]);
337
338 let mut table = FingerTable::new(dids[0], 5);
339
340 table.reset_finger();
342 table.set(0, did1);
343 table.set(1, did2);
344 table.set(2, did3);
345 table.set(3, did4);
346 table.set(4, did5);
347 table.remove(did1);
348 assert_eq!(table.finger, [
349 Some(did2),
350 Some(did2),
351 Some(did3),
352 Some(did4),
353 Some(did5),
354 ]);
355
356 table.reset_finger();
358 table.set(0, did1);
359 table.set(1, did2);
360 table.set(2, did3);
361 table.set(3, did4);
362 table.set(4, did5);
363 table.remove(did2);
364 assert_eq!(table.finger, [
365 Some(did1),
366 Some(did3),
367 Some(did3),
368 Some(did4),
369 Some(did5),
370 ]);
371
372 table.reset_finger();
374 table.set(0, did1);
375 table.set(2, did3);
376 table.set(3, did4);
377 table.set(4, did5);
378 table.remove(did1);
379 assert_eq!(table.finger, [
380 None,
381 None,
382 Some(did3),
383 Some(did4),
384 Some(did5),
385 ]);
386
387 table.reset_finger();
389 table.set(0, did1);
390 table.set(2, did3);
391 table.set(3, did4);
392 table.set(4, did5);
393 table.remove(did3);
394 assert_eq!(table.finger, [
395 Some(did1),
396 None,
397 Some(did4),
398 Some(did4),
399 Some(did5),
400 ]);
401
402 table.reset_finger();
404 table.set(0, did1);
405 table.set(1, did2);
406 table.set(2, did3);
407 table.set(3, did4);
408 table.set(4, did5);
409 table.remove(did5);
410 assert_eq!(table.finger, [
411 Some(did1),
412 Some(did2),
413 Some(did3),
414 Some(did4),
415 None
416 ]);
417 }
418}