cfdp_simplified/daemon/
timer.rs1use std::time::{Duration, Instant};
2
3#[derive(Debug)]
4pub struct Counter {
5 start_time: Instant,
6 timeout: Duration,
7 max_count: u32,
8 count: u32,
9 occurred: bool,
10 paused: bool,
11}
12impl Counter {
13 pub fn new(timeout: Duration, max_count: u32) -> Self {
14 Self {
15 max_count,
16 timeout,
17 count: 0,
18 start_time: Instant::now(),
19 occurred: false,
20 paused: true,
21 }
22 }
23 fn restart(&mut self) {
27 self.update();
28 self.start_time = Instant::now();
29 self.paused = false;
30 self.occurred = false;
31 }
32
33 fn reset(&mut self) {
37 self.start_time = Instant::now();
38 self.paused = false;
39 self.occurred = false;
40 self.count = 0;
41 }
42
43 fn update(&mut self) {
44 if self.paused {
45 return;
46 }
47 let now = Instant::now();
48 while now.duration_since(self.start_time) >= self.timeout {
49 self.count = (self.count + 1).clamp(0, self.max_count);
50 self.start_time += self.timeout;
51 self.occurred = true;
52 }
53 }
54
55 pub fn pause(&mut self) {
56 self.update();
57 self.paused = true;
58 }
59
60 pub fn start(&mut self) {
61 self.paused = false;
62 }
63
64 pub fn limit_reached(&mut self) -> bool {
65 self.update();
66 self.count == self.max_count
67 }
68
69 pub fn timeout_occurred(&mut self) -> bool {
70 self.update();
71 self.occurred
72 }
73
74 pub fn until_timeout(&self) -> Duration {
75 let next_timeout = self.start_time + self.timeout;
76 let now = Instant::now();
77 if next_timeout > now {
78 next_timeout.duration_since(now)
79 } else {
80 Duration::ZERO
81 }
82 }
83
84 #[cfg(test)]
85 pub fn get_count(&self) -> u32 {
86 self.count
87 }
88
89 #[cfg(test)]
90 pub fn is_ticking(&self) -> bool {
91 !self.paused
92 }
93}
94
95#[derive(Debug)]
96pub struct Timer {
97 pub inactivity: Counter,
98 pub nak: Counter,
99 pub eof: Counter,
100 pub progress_report: Counter,
101}
102impl Timer {
103 pub fn new(
104 inactivity_timeout: i64,
105 inactivity_max_count: u32,
106 eof_timeout: i64,
107 eof_max_count: u32,
108 nak_timeout: i64,
109 nak_max_count: u32,
110 progress_report_interval_secs: i64,
111 ) -> Self {
112 Self {
113 inactivity: Counter::new(
114 Duration::from_secs(inactivity_timeout as u64),
115 inactivity_max_count,
116 ),
117 eof: Counter::new(Duration::from_secs(eof_timeout as u64), eof_max_count),
118 nak: Counter::new(Duration::from_secs(nak_timeout as u64), nak_max_count),
119 progress_report: Counter::new(
120 Duration::from_secs(progress_report_interval_secs as u64),
121 u32::MAX,
122 ),
123 }
124 }
125
126 pub fn restart_inactivity(&mut self) {
127 self.inactivity.restart()
128 }
129
130 pub fn reset_inactivity(&mut self) {
131 self.inactivity.reset()
132 }
133
134 pub fn restart_eof(&mut self) {
135 self.eof.restart()
136 }
137
138 pub fn reset_eof(&mut self) {
139 self.eof.reset()
140 }
141
142 pub fn restart_nak(&mut self) {
143 self.nak.restart()
144 }
145
146 pub fn reset_nak(&mut self) {
147 self.nak.reset()
148 }
149
150 pub fn reset_progress_report(&mut self) {
151 self.progress_report.reset()
152 }
153 pub fn until_timeout(&self) -> Duration {
156 let mut min = Duration::MAX;
157
158 if !self.eof.paused {
159 min = Duration::min(min, self.eof.until_timeout());
160 }
161
162 if !self.nak.paused {
163 min = Duration::min(min, self.nak.until_timeout());
164 }
165
166 if !self.inactivity.paused {
167 min = Duration::min(min, self.inactivity.until_timeout());
168 }
169
170 if !self.progress_report.paused {
171 min = Duration::min(min, self.progress_report.until_timeout());
172 }
173 min
174 }
175}
176
177#[cfg(test)]
178mod test {
179 use super::*;
180
181 use std::{thread, time::Duration};
182
183 #[test]
184 fn timeout() {
185 let mut timer = Timer::new(1_i64, 5, 1_i64, 5, 1_i64, 5, 1_i64);
186 timer.restart_inactivity();
187 thread::sleep(Duration::from_secs_f32(2.5_f32));
188 timer.inactivity.pause();
189 assert_eq!(timer.inactivity.get_count(), 2);
190 assert!(!timer.inactivity.limit_reached());
191 assert!(timer.inactivity.timeout_occurred())
192 }
193
194 #[test]
195 fn no_timeout() {
196 let mut timer = Timer::new(3_i64, 5, 1_i64, 5, 1_i64, 5, 1_i64);
197 timer.restart_inactivity();
198 thread::sleep(Duration::from_secs_f32(1.1_f32));
199 timer.inactivity.pause();
200 assert!(!timer.inactivity.timeout_occurred());
201 thread::sleep(Duration::from_secs_f32(1.5_f32));
203 assert!(!timer.inactivity.timeout_occurred());
204
205 assert_eq!(timer.inactivity.get_count(), 0)
206 }
207
208 #[test]
209 fn limit() {
210 let mut timer = Timer::new(1_i64, 1, 1_i64, 5, 1_i64, 5, 1_i64);
211 timer.restart_inactivity();
212 thread::sleep(Duration::from_secs_f32(1.5));
213 assert!(timer.inactivity.limit_reached());
214 thread::sleep(Duration::from_secs_f32(1.5));
216 assert!(timer.inactivity.limit_reached());
217 assert_eq!(timer.inactivity.get_count(), 1);
218 }
219
220 #[test]
221 fn restart_no_fail() {
222 let mut timer = Timer::new(2_i64, 5, 1_i64, 5, 1_i64, 5, 1_64);
223 timer.restart_inactivity();
224 thread::sleep(Duration::from_secs_f32(1.5));
225 assert!(!timer.inactivity.timeout_occurred());
226 timer.restart_inactivity();
227 thread::sleep(Duration::from_secs_f32(2.2));
228 timer.inactivity.pause();
229
230 assert!(timer.inactivity.timeout_occurred())
231 }
232
233 #[test]
234 fn timeout_all() {
235 let mut timer = Timer::new(1_i64, 5, 1_i64, 5, 1_i64, 5, 1_i64);
236 timer.restart_inactivity();
237 timer.restart_eof();
238 timer.restart_nak();
239 timer.reset_progress_report();
240 thread::sleep(Duration::from_secs_f32(1.5));
241 assert!(timer.inactivity.timeout_occurred());
242 assert!(timer.eof.timeout_occurred());
243 assert!(timer.nak.timeout_occurred());
244 assert!(timer.progress_report.timeout_occurred());
245 assert_eq!(timer.inactivity.get_count(), 1);
246 assert_eq!(timer.eof.get_count(), 1);
247 assert_eq!(timer.nak.get_count(), 1);
248 assert_eq!(timer.progress_report.get_count(), 1);
249 }
250}