Skip to main content

tor_hsservice/publish/
reupload_timer.rs

1//! Helper types used by the [`Reactor`] for scheduling descriptor reuploads.
2
3use super::*;
4
5/// A type that represents when a descriptor should be republished.
6///
7/// A `ReuploadTimer` is "greater" than another if its `when` timestamp is earlier.
8///
9/// This type is used in a max-heap to extract the earliest reupload the publisher can schedule.
10#[derive(Clone, Copy, Debug)]
11pub(super) struct ReuploadTimer {
12    /// The TP for which to republish the descriptor.
13    pub(super) period: TimePeriod,
14    /// The earliest time when the descriptor should be republished.
15    pub(super) when: Instant,
16}
17
18impl Ord for ReuploadTimer {
19    fn cmp(&self, other: &Self) -> Ordering {
20        // Reversed, because we want the earlier
21        // `ReuploadTimer` to be "greater".
22        self.when.cmp(&other.when).reverse()
23    }
24}
25
26impl PartialOrd for ReuploadTimer {
27    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
28        Some(self.cmp(other))
29    }
30}
31
32impl PartialEq for ReuploadTimer {
33    fn eq(&self, other: &Self) -> bool {
34        self.when == other.when
35    }
36}
37
38impl Eq for ReuploadTimer {}
39
40#[cfg(test)]
41mod test {
42    // @@ begin test lint list maintained by maint/add_warning @@
43    #![allow(clippy::bool_assert_comparison)]
44    #![allow(clippy::clone_on_copy)]
45    #![allow(clippy::dbg_macro)]
46    #![allow(clippy::mixed_attributes_style)]
47    #![allow(clippy::print_stderr)]
48    #![allow(clippy::print_stdout)]
49    #![allow(clippy::single_char_pattern)]
50    #![allow(clippy::unwrap_used)]
51    #![allow(clippy::unchecked_time_subtraction)]
52    #![allow(clippy::useless_vec)]
53    #![allow(clippy::needless_pass_by_value)]
54    #![allow(clippy::string_slice)] // See arti#2571
55    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
56    use std::collections::BinaryHeap;
57
58    use super::*;
59    use web_time_compat::InstantExt;
60
61    #[test]
62    fn reupload_for_time_period_ordering() {
63        const ONE_SEC: Duration = Duration::from_secs(1);
64
65        let now = Instant::get();
66        let later = now + ONE_SEC;
67        let later_still = now + ONE_SEC * 2;
68        let timer1 = ReuploadTimer {
69            period: TimePeriod::from_parts(1, 2, 3),
70            when: now,
71        };
72
73        let timer2 = ReuploadTimer {
74            period: TimePeriod::from_parts(4, 5, 6),
75            when: later,
76        };
77
78        let timer3 = ReuploadTimer {
79            period: TimePeriod::from_parts(7, 8, 9),
80            when: later_still,
81        };
82
83        for timer in &[timer1, timer2, timer3] {
84            assert_eq!(timer, timer);
85        }
86
87        assert_ne!(timer1, timer2);
88        assert_ne!(timer1, timer3);
89        assert_ne!(timer2, timer3);
90
91        assert!(timer1 > timer2);
92        assert!(timer1 > timer3);
93        assert!(timer2 > timer3);
94
95        // A ReuploadTimer same `when`, but a different `time_period`.
96        let mut timer4 = timer1;
97        timer4.period = TimePeriod::from_parts(9, 9, 9);
98        assert_ne!(timer1.period, timer4.period);
99        assert_eq!(timer1, timer4);
100
101        let mut heap = BinaryHeap::default();
102        for timer in &[timer3, timer2, timer1] {
103            heap.push(*timer);
104        }
105
106        assert_eq!(heap.pop(), Some(timer1));
107        assert_eq!(heap.pop(), Some(timer2));
108        assert_eq!(heap.pop(), Some(timer3));
109        assert_eq!(heap.pop(), None);
110    }
111}