aboutsummaryrefslogtreecommitdiff
path: root/crates/tor-hsservice/src/publish/reupload_timer.rs
blob: 26af333e522783b49cb764f1a5ea249fca076427 (plain)
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
//! Helper types used by the [`Reactor`] for scheduling descriptor reuploads.

use super::*;

/// A type that represents when a descriptor should be republished.
///
/// A `ReuploadTimer` is "greater" than another if its `when` timestamp is earlier.
///
/// This type is used in a max-heap to extract the earliest reupload the publisher can schedule.
#[derive(Clone, Copy, Debug)]
pub(super) struct ReuploadTimer {
    /// The TP for which to republish the descriptor.
    pub(super) period: TimePeriod,
    /// The earliest time when the descriptor should be republished.
    pub(super) when: Instant,
}

impl Ord for ReuploadTimer {
    fn cmp(&self, other: &Self) -> Ordering {
        // Reversed, because we want the earlier
        // `ReuploadTimer` to be "greater".
        self.when.cmp(&other.when).reverse()
    }
}

impl PartialOrd for ReuploadTimer {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for ReuploadTimer {
    fn eq(&self, other: &Self) -> bool {
        self.when == other.when
    }
}

impl Eq for ReuploadTimer {}

#[cfg(test)]
mod test {
    // @@ begin test lint list maintained by maint/add_warning @@
    #![allow(clippy::bool_assert_comparison)]
    #![allow(clippy::clone_on_copy)]
    #![allow(clippy::dbg_macro)]
    #![allow(clippy::mixed_attributes_style)]
    #![allow(clippy::print_stderr)]
    #![allow(clippy::print_stdout)]
    #![allow(clippy::single_char_pattern)]
    #![allow(clippy::unwrap_used)]
    #![allow(clippy::unchecked_time_subtraction)]
    #![allow(clippy::useless_vec)]
    #![allow(clippy::needless_pass_by_value)]
    #![allow(clippy::string_slice)] // See arti#2571
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
    use std::collections::BinaryHeap;

    use super::*;
    use web_time_compat::InstantExt;

    #[test]
    fn reupload_for_time_period_ordering() {
        const ONE_SEC: Duration = Duration::from_secs(1);

        let now = Instant::get();
        let later = now + ONE_SEC;
        let later_still = now + ONE_SEC * 2;
        let timer1 = ReuploadTimer {
            period: TimePeriod::from_parts(1, 2, 3),
            when: now,
        };

        let timer2 = ReuploadTimer {
            period: TimePeriod::from_parts(4, 5, 6),
            when: later,
        };

        let timer3 = ReuploadTimer {
            period: TimePeriod::from_parts(7, 8, 9),
            when: later_still,
        };

        for timer in &[timer1, timer2, timer3] {
            assert_eq!(timer, timer);
        }

        assert_ne!(timer1, timer2);
        assert_ne!(timer1, timer3);
        assert_ne!(timer2, timer3);

        assert!(timer1 > timer2);
        assert!(timer1 > timer3);
        assert!(timer2 > timer3);

        // A ReuploadTimer same `when`, but a different `time_period`.
        let mut timer4 = timer1;
        timer4.period = TimePeriod::from_parts(9, 9, 9);
        assert_ne!(timer1.period, timer4.period);
        assert_eq!(timer1, timer4);

        let mut heap = BinaryHeap::default();
        for timer in &[timer3, timer2, timer1] {
            heap.push(*timer);
        }

        assert_eq!(heap.pop(), Some(timer1));
        assert_eq!(heap.pop(), Some(timer2));
        assert_eq!(heap.pop(), Some(timer3));
        assert_eq!(heap.pop(), None);
    }
}