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 - attempted to insert a duplicate child account")]
24 ChildAccountAlreadyExists,
25
26 #[error("memquota - attempt to allocate by torn-down memory tracking participant")]
30 ParticipantShutdown,
31
32 #[error("{TrackerCorrupted}")]
34 TrackerCorrupted,
35
36 #[error("internal error")]
38 Bug(#[from] Bug),
39}
40
41#[derive(Debug, Clone, Error, Default)]
49#[non_exhaustive]
50#[error("{0}")]
51pub struct MemoryReclaimedError(ReclaimedErrorInner);
52
53#[derive(Debug, Clone, Error, Default)]
56enum ReclaimedErrorInner {
57 #[error("data structure discarded due to memory pressure")]
59 #[default]
60 Collapsed,
61
62 #[error("{0}")]
64 TrackerError(#[from] Error),
65}
66
67#[derive(Debug, Clone, Error)]
69#[non_exhaustive]
70pub enum StartupError {
71 #[error("couldn't spawn reclamation task")]
73 Spawn(#[source] Arc<SpawnError>),
74}
75
76impl From<SpawnError> for StartupError {
77 fn from(e: SpawnError) -> StartupError {
78 StartupError::Spawn(Arc::new(e))
79 }
80}
81
82#[derive(Debug, Clone, Error)]
89#[error("memory tracker is corrupted due to previous bug")]
90pub struct TrackerCorrupted;
91
92impl<T> From<PoisonError<T>> for TrackerCorrupted {
93 fn from(_: PoisonError<T>) -> TrackerCorrupted {
94 TrackerCorrupted
95 }
96}
97
98impl From<TrackerCorrupted> for Error {
99 fn from(_: TrackerCorrupted) -> Error {
100 Error::TrackerCorrupted
101 }
102}
103
104#[derive(Debug, Clone, Error)]
108pub(crate) enum ReclaimCrashed {
109 #[error("memory tracker corrupted due to previous bug")]
111 TrackerCorrupted(#[from] TrackerCorrupted),
112
113 #[error("internal error")]
115 Bug(#[from] Bug),
116}
117
118impl MemoryReclaimedError {
119 pub fn new() -> Self {
121 MemoryReclaimedError::default()
122 }
123}
124
125impl From<Error> for MemoryReclaimedError {
126 fn from(e: Error) -> MemoryReclaimedError {
127 MemoryReclaimedError(e.into())
128 }
129}
130
131impl HasKind for MemoryReclaimedError {
132 fn kind(&self) -> ErrorKind {
133 self.0.kind()
134 }
135}
136
137impl HasKind for ReclaimedErrorInner {
138 fn kind(&self) -> ErrorKind {
139 use ErrorKind as EK;
140 use ReclaimedErrorInner as REI;
141 match self {
142 REI::Collapsed => EK::LocalResourceExhausted,
143 REI::TrackerError(e) => e.kind(),
144 }
145 }
146}
147
148impl HasKind for Error {
149 fn kind(&self) -> ErrorKind {
150 use Error as E;
151 use ErrorKind as EK;
152 match self {
153 E::TrackerShutdown => EK::ArtiShuttingDown,
154 E::AccountClosed => EK::LocalResourceExhausted,
155 E::ChildAccountAlreadyExists => EK::BadApiUsage,
156 E::ParticipantShutdown => EK::LocalResourceExhausted,
157 E::TrackerCorrupted => EK::Internal,
158 E::Bug(e) => e.kind(),
159 }
160 }
161}
162
163impl HasKind for TrackerCorrupted {
164 fn kind(&self) -> ErrorKind {
165 use ErrorKind as EK;
166 match self {
167 TrackerCorrupted => EK::Internal,
168 }
169 }
170}
171
172impl HasKind for StartupError {
173 fn kind(&self) -> ErrorKind {
174 use StartupError as SE;
175 match self {
176 SE::Spawn(e) => e.kind(),
177 }
178 }
179}
180
181impl HasKind for ReclaimCrashed {
182 fn kind(&self) -> ErrorKind {
183 use ReclaimCrashed as RC;
184 match self {
185 RC::TrackerCorrupted(e) => e.kind(),
186 RC::Bug(e) => e.kind(),
187 }
188 }
189}
190
191#[cfg(test)]
192mod test {
193 #![allow(clippy::bool_assert_comparison)]
195 #![allow(clippy::clone_on_copy)]
196 #![allow(clippy::dbg_macro)]
197 #![allow(clippy::mixed_attributes_style)]
198 #![allow(clippy::print_stderr)]
199 #![allow(clippy::print_stdout)]
200 #![allow(clippy::single_char_pattern)]
201 #![allow(clippy::unwrap_used)]
202 #![allow(clippy::unchecked_time_subtraction)]
203 #![allow(clippy::useless_vec)]
204 #![allow(clippy::needless_pass_by_value)]
205 use super::*;
207 use fmt::Display;
208
209 #[test]
210 fn error_display() {
211 fn check_value(e: impl Debug + Display + HasKind) {
212 println!("{e:?} / {e} / {:?}", e.kind());
213 }
214
215 let bug = internal!("error made for testingr");
216
217 macro_rules! check_enum { {
218 $ty:ident: $( $variant:ident $fields:tt; )*
220 } => {
221 for e in [ $(
222 $ty::$variant $fields,
223 )* ] {
224 check_value(e);
225 }
226 match None::<$ty> {
227 None => {}
228 $( Some($ty::$variant { .. }) => {}, )*
229 }
230 } }
231
232 check_enum! {
233 Error:
234 TrackerShutdown {};
235 AccountClosed {};
236 ChildAccountAlreadyExists {};
237 ParticipantShutdown {};
238 TrackerCorrupted {};
239 Bug(bug.clone());
240 }
241
242 check_enum! {
243 ReclaimedErrorInner:
244 Collapsed {};
245 TrackerError(Error::TrackerShutdown);
246 }
247
248 check_value(MemoryReclaimedError(ReclaimedErrorInner::Collapsed));
249
250 check_enum! {
251 StartupError:
252 Spawn(SpawnError::shutdown().into());
253 }
254
255 check_value(TrackerCorrupted);
256
257 check_enum! {
258 ReclaimCrashed:
259 TrackerCorrupted(TrackerCorrupted);
260 Bug(bug.clone());
261 }
262 }
263}