tor_memquota/
error.rs
1use crate::internal_prelude::*;
4
5#[derive(Debug, Clone, Error)]
7#[non_exhaustive]
8pub enum Error {
9 #[error("attempted to use shut down memory tracker")]
11 TrackerShutdown,
12
13 #[error("memquota - attempted to use closed memory tracking account")]
17 AccountClosed,
18
19 #[error("memquota - attempt to allocate by torn-down memory tracking participant")]
23 ParticipantShutdown,
24
25 #[error("{TrackerCorrupted}")]
27 TrackerCorrupted,
28
29 #[error("internal error")]
31 Bug(#[from] Bug),
32}
33
34#[derive(Debug, Clone, Error, Default)]
42#[non_exhaustive]
43#[error("{0}")]
44pub struct MemoryReclaimedError(ReclaimedErrorInner);
45
46#[derive(Debug, Clone, Error, Default)]
49enum ReclaimedErrorInner {
50 #[error("data structure discarded due to memory pressure")]
52 #[default]
53 Collapsed,
54
55 #[error("{0}")]
57 TrackerError(#[from] Error),
58}
59
60#[derive(Debug, Clone, Error)]
62#[non_exhaustive]
63pub enum StartupError {
64 #[error("couldn't spawn reclamation task")]
66 Spawn(#[source] Arc<SpawnError>),
67}
68
69impl From<SpawnError> for StartupError {
70 fn from(e: SpawnError) -> StartupError {
71 StartupError::Spawn(Arc::new(e))
72 }
73}
74
75#[derive(Debug, Clone, Error)]
82#[error("memory tracker is corrupted due to previous bug")]
83pub struct TrackerCorrupted;
84
85impl<T> From<PoisonError<T>> for TrackerCorrupted {
86 fn from(_: PoisonError<T>) -> TrackerCorrupted {
87 TrackerCorrupted
88 }
89}
90
91impl From<TrackerCorrupted> for Error {
92 fn from(_: TrackerCorrupted) -> Error {
93 Error::TrackerCorrupted
94 }
95}
96
97#[derive(Debug, Clone, Error)]
101pub(crate) enum ReclaimCrashed {
102 #[error("memory tracker corrupted due to previous bug")]
104 TrackerCorrupted(#[from] TrackerCorrupted),
105
106 #[error("internal error")]
108 Bug(#[from] Bug),
109}
110
111impl MemoryReclaimedError {
112 pub fn new() -> Self {
114 MemoryReclaimedError::default()
115 }
116}
117
118impl From<Error> for MemoryReclaimedError {
119 fn from(e: Error) -> MemoryReclaimedError {
120 MemoryReclaimedError(e.into())
121 }
122}
123
124impl HasKind for MemoryReclaimedError {
125 fn kind(&self) -> ErrorKind {
126 self.0.kind()
127 }
128}
129
130impl HasKind for ReclaimedErrorInner {
131 fn kind(&self) -> ErrorKind {
132 use ErrorKind as EK;
133 use ReclaimedErrorInner as REI;
134 match self {
135 REI::Collapsed => EK::LocalResourceExhausted,
136 REI::TrackerError(e) => e.kind(),
137 }
138 }
139}
140
141impl HasKind for Error {
142 fn kind(&self) -> ErrorKind {
143 use Error as E;
144 use ErrorKind as EK;
145 match self {
146 E::TrackerShutdown => EK::ArtiShuttingDown,
147 E::AccountClosed => EK::LocalResourceExhausted,
148 E::ParticipantShutdown => EK::LocalResourceExhausted,
149 E::TrackerCorrupted => EK::Internal,
150 E::Bug(e) => e.kind(),
151 }
152 }
153}
154
155impl HasKind for TrackerCorrupted {
156 fn kind(&self) -> ErrorKind {
157 use ErrorKind as EK;
158 match self {
159 TrackerCorrupted => EK::Internal,
160 }
161 }
162}
163
164impl HasKind for StartupError {
165 fn kind(&self) -> ErrorKind {
166 use StartupError as SE;
167 match self {
168 SE::Spawn(e) => e.kind(),
169 }
170 }
171}
172
173impl HasKind for ReclaimCrashed {
174 fn kind(&self) -> ErrorKind {
175 use ReclaimCrashed as RC;
176 match self {
177 RC::TrackerCorrupted(e) => e.kind(),
178 RC::Bug(e) => e.kind(),
179 }
180 }
181}
182
183#[cfg(test)]
184mod test {
185 #![allow(clippy::bool_assert_comparison)]
187 #![allow(clippy::clone_on_copy)]
188 #![allow(clippy::dbg_macro)]
189 #![allow(clippy::mixed_attributes_style)]
190 #![allow(clippy::print_stderr)]
191 #![allow(clippy::print_stdout)]
192 #![allow(clippy::single_char_pattern)]
193 #![allow(clippy::unwrap_used)]
194 #![allow(clippy::unchecked_duration_subtraction)]
195 #![allow(clippy::useless_vec)]
196 #![allow(clippy::needless_pass_by_value)]
197 use super::*;
199 use fmt::Display;
200
201 #[test]
202 fn error_display() {
203 fn check_value(e: impl Debug + Display + HasKind) {
204 println!("{e:?} / {e} / {:?}", e.kind());
205 }
206
207 let bug = internal!("error made for testingr");
208
209 macro_rules! check_enum { {
210 $ty:ident: $( $variant:ident $fields:tt; )*
212 } => {
213 for e in [ $(
214 $ty::$variant $fields,
215 )* ] {
216 check_value(e);
217 }
218 match None::<$ty> {
219 None => {}
220 $( Some($ty::$variant { .. }) => {}, )*
221 }
222 } }
223
224 check_enum! {
225 Error:
226 TrackerShutdown {};
227 AccountClosed {};
228 ParticipantShutdown {};
229 TrackerCorrupted {};
230 Bug(bug.clone());
231 }
232
233 check_enum! {
234 ReclaimedErrorInner:
235 Collapsed {};
236 TrackerError(Error::TrackerShutdown);
237 }
238
239 check_value(MemoryReclaimedError(ReclaimedErrorInner::Collapsed));
240
241 check_enum! {
242 StartupError:
243 Spawn(SpawnError::shutdown().into());
244 }
245
246 check_value(TrackerCorrupted);
247
248 check_enum! {
249 ReclaimCrashed:
250 TrackerCorrupted(TrackerCorrupted);
251 Bug(bug.clone());
252 }
253 }
254}