1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::*;
use std::{
    num::Wrapping,
    ops::{Bound, RangeBounds},
};

/// Check a set of peers the actual redundancy across all peers.
/// This can tell if there is bad distribution.
/// Note this function is only used for verification in tests at this time.
pub fn check_redundancy(peers: Vec<DhtArc>) -> u32 {
    use std::collections::HashSet;
    #[derive(Clone, Copy, Debug)]
    enum Side {
        Left,
        Right,
    }
    #[derive(Clone, Copy, Debug)]
    struct Arm {
        id: usize,
        side: Side,
        pos: u32,
    }
    let left = |arc: &DhtArc| match arc.range().start_bound() {
        Bound::Included(arm) => *arm,
        _ => unreachable!(),
    };
    let right = |arc: &DhtArc| match arc.range().end_bound() {
        Bound::Included(arm) => *arm,
        _ => unreachable!(),
    };

    // Turn each arc into a side with a unique id that is
    // shared by both sides.
    let mut id = 0;
    let mut sides = |arc: &DhtArc| {
        let i = id;
        let l = Arm {
            id: i,
            side: Side::Left,
            pos: left(arc),
        };
        let r = Arm {
            id: i,
            side: Side::Right,
            pos: right(arc),
        };
        id += 1;
        vec![l, r]
    };

    // Record and remove any full redundancy arcs as we only
    // need to measure that stack of partial coverage.
    let mut full_r = 0;
    let peers: Vec<_> = peers
        .into_iter()
        .filter(|a| {
            if (a.coverage() - 1.0).abs() < ERROR_MARGIN {
                full_r += 1;
                false
            } else {
                // Also remove any bounds that don't include some coverage.
                matches!(a.range().start_bound(), Bound::Included(_))
            }
        })
        .collect();

    // If we are empty at this stage then return any full coverage.
    if peers.is_empty() {
        return full_r;
    }

    // Turn the rest of the partial arcs into their sides.
    let mut peers = peers
        .into_iter()
        .flat_map(|p| sides(&p).into_iter())
        .collect::<Vec<_>>();

    // Sort the sides by their positions.
    peers.sort_unstable_by_key(|p| p.pos);

    // Fold over the sides tracking the stack of arcs that have been entered but not exited.
    // The minimal stack height at any given point is the minimum redundancy on the network.
    let stack_fold = |(mut stack, r, mut started, mut last_remove): (
        HashSet<usize>,
        usize,
        bool,
        Option<u32>,
    ),
                      arm: &Arm| {
        let mut connected = false;
        let mut this_remove = None;
        match arm.side {
            Side::Left => {
                // We must have added at least one arc otherwise
                // our minimum stack height will always be one.
                started = true;

                // Check if we are inserting an arc just one location
                // past a remove because that actually counts as covered.
                connected = last_remove
                    .as_ref()
                    .map(|l| (Wrapping(arm.pos) - Wrapping(*l)).0 <= 1)
                    .unwrap_or(false);

                // Add this id to the stack.
                stack.insert(arm.id);
            }
            Side::Right => {
                // Set the last removed.
                this_remove = Some(arm.pos);

                // Remove this id.
                stack.remove(&arm.id);
            }
        }
        // Get the current stack height.
        let len = stack.len();

        // If we have started and the length has dropped then set a
        // lower redundancy.
        let mut r = if len < r && started {
            // Only record removes that actually change the r level.
            last_remove = this_remove;
            len
        } else {
            r
        };

        // If this was actually a connected insert then undo the last remove.
        if connected {
            r += 1
        }
        (stack, r, started, last_remove)
    };

    // Run through the list once to find the stack remaining at the end of the run.
    let (stack, _, started, last_removed) = peers
        .iter()
        .fold((HashSet::new(), usize::MAX, false, None), stack_fold);

    // Now use that as the starting stack for the "real" run.
    let (_, r, _, _) = peers
        .iter()
        .fold((stack, usize::MAX, started, last_removed), stack_fold);

    // Our redundancy is whatever partial + any full redundancy
    r as u32 + full_r
}