1use std::path::PathBuf;
2
3use thiserror::Error;
4
5
6#[macro_export]
8macro_rules! function_name {
9 () => {{
10 use clippy_utilities::OverflowArithmetic;
11 fn f() {}
12 fn type_name_of<T>(_: T) -> &'static str {
13 std::any::type_name::<T>()
14 }
15 let name = type_name_of(f);
16 name.get(..name.len().overflow_sub(3))
18 .unwrap_or_else(|| unreachable!("Suffix `::f` must exist."))
19 }};
20}
21
22pub type AsyncFusexResult<T> = Result<T, AsyncFusexError>;
23#[derive(Error, Debug)]
24pub enum AsyncFusexError {
25 #[error("IoErr, the error is {:?}, context is {:#?}", .source, .context)]
27 IoErr {
28 source: std::io::Error,
30 context: Vec<String>,
32 },
33
34 #[error("WalkdirErr, the error is {:?}, context is {:#?}", .source, .context)]
36 WalkdirErr {
37 source: walkdir::Error,
39 context: Vec<String>,
41 },
42
43 #[error("Snapshot ID={} not found, context is {:#?}", .snapshot_id, .context)]
45 SnapshotNotFound {
46 snapshot_id: String,
48 context: Vec<String>,
50 },
51 #[error("Volume ID={} not found, context is {:#?}", .volume_id, .context)]
53 VolumeNotFound {
54 volume_id: String,
56 context: Vec<String>,
58 },
59 #[error("Volume ID={} already exists, context is {:#?}", .volume_id, .context)]
61 VolumeAlreadyExist {
62 volume_id: String,
64 context: Vec<String>,
66 },
67
68 #[error("Snapshot ID={} is not ready, context is {:#?}", .snapshot_id, .context)]
70 SnapshotNotReady {
71 snapshot_id: String,
73 context: Vec<String>,
75 },
76
77 #[error("Snapshot ID={} already exists, context is {:#?}", .snapshot_id, .context)]
79 SnapshotAlreadyExist {
80 snapshot_id: String,
82 context: Vec<String>,
84 },
85
86 #[error("Node ID={} not found, context is {:#?}", .node_id, .context)]
88 NodeNotFound {
89 node_id: String,
91 context: Vec<String>,
93 },
94
95 #[error("Argument is invalid, context is {:#?}", .context)]
97 ArgumentInvalid {
98 context: Vec<String>,
100 },
101
102 #[error("Starting token={} is invalid, context is {:#?}", .starting_token, .context)]
104 StartingTokenInvalid {
105 starting_token: String,
107 context: Vec<String>,
109 },
110
111 #[error("Argument is out of range, context is {:#?}", .context)]
113 ArgumentOutOfRange {
114 context: Vec<String>,
116 },
117
118 #[error("StripPrefixErr, the error is {:?}, context is {:#?}", .source, .context)]
120 StripPrefixErr {
121 source: std::path::StripPrefixError,
123 context: Vec<String>,
125 },
126
127 #[error("NixErr, the error is {:?}, context is {:#?}", .source, .context)]
129 NixErr {
130 source: nix::Error,
132 context: Vec<String>,
134 },
135
136 #[error("MountErr, fail to mount {:?} to {:?}, context is {:#?}", .from, .target, .context)]
138 MountErr {
139 from: PathBuf,
141 target: PathBuf,
143 context: Vec<String>,
145 },
146
147 #[error("UmountErr, fail to umount {:?}, context is {:#?}", .target, .context)]
149 UmountErr {
150 target: PathBuf,
152 context: Vec<String>,
154 },
155
156 #[error("SystemTimeErr, the error is {:?}, context is {:#?}", .source, .context)]
158 SystemTimeErr {
159 source: std::time::SystemTimeError,
161 context: Vec<String>,
163 },
164
165
166 #[error("tokio::task::JoinError, the error is {:?}, context is {:#?}", .source, .context)]
168 JoinErr {
169 source: tokio::task::JoinError,
171 context: Vec<String>,
173 },
174
175 #[error("TransactionRetryLimitExceededErr, context is {:#?}", .context)]
177 TransactionRetryLimitExceededErr {
178 context: Vec<String>,
180 },
181
182 #[error("InternalErr, the error is {} context is {:#?}", .source,.context)]
184 InternalErr {
185 source: anyhow::Error,
187 context: Vec<String>,
189 },
190
191 #[error("Not implemented, context is {:#?}", .context)]
193 Unimplemented {
194 context: Vec<String>,
196 },
197 #[error("FS is inconsistent, context is {:#?}.", .context)]
199 InconsistentFS {
200 context: Vec<String>,
202 },
203 #[error("Cache cluster error, context is {:#?}.", .context)]
205 CacheClusterErr {
206 context: Vec<String>,
208 },
209 #[error("Distribute cache manager error, context is {:#?}.", .context)]
211 DistributeCacheManagerErr {
212 context: Vec<String>,
214 },
215 }
223
224pub trait Context<T, E> {
225 fn add_context<C>(self, ctx: C) -> AsyncFusexResult<T>
226 where
227 C: Into<String>;
228
229 fn with_context<C, F>(self, f: F) -> AsyncFusexResult<T>
230 where
231 C: Into<String>,
232 F: FnOnce() -> C;
233}
234
235impl<T, E> Context<T, E> for Result<T, E>
236where
237 E: std::error::Error + Into<AsyncFusexError>,
238{
239 #[inline]
240 fn add_context<C>(self, ctx: C) -> AsyncFusexResult<T>
241 where
242 C: Into<String>,
243 {
244 self.map_err(|err| err.into().add_context(ctx))
245 }
246
247 #[inline]
248 fn with_context<C, F>(self, context_func: F) -> AsyncFusexResult<T>
249 where
250 C: Into<String>,
251 F: FnOnce() -> C,
252 {
253 self.map_err(|err| err.into().add_context(context_func()))
254 }
255}
256
257impl AsyncFusexError {
258 #[inline]
259 #[must_use]
260 pub fn add_context<C>(mut self, ctx: C) -> Self
261 where
262 C: Into<String>,
263 {
264 macro_rules! append_context {
265 ($context: ident, [$($target:ident),*]) => {
266 match self {
267 $(Self::$target { ref mut context, ..} => {
268 context.push($context.into());
269 },)*
270 }
271 }
272 }
273 append_context!(
274 ctx,
275 [
276 IoErr,
277 WalkdirErr,
278 SnapshotNotFound,
279 VolumeNotFound,
280 VolumeAlreadyExist,
281 SnapshotNotReady,
282 SnapshotAlreadyExist,
283 NodeNotFound,
284 ArgumentInvalid,
285 StartingTokenInvalid,
286 ArgumentOutOfRange,
287 StripPrefixErr,
288 NixErr,
289 MountErr,
290 UmountErr,
291 SystemTimeErr,
292 JoinErr,
293 TransactionRetryLimitExceededErr,
294 InternalErr,
295 Unimplemented,
296 InconsistentFS,
297 CacheClusterErr,
298 DistributeCacheManagerErr
299 ]
300 );
301 self
302 }
303
304 #[inline]
305 #[must_use]
306 pub fn with_context<C, F>(self, context_fn: F) -> Self
307 where
308 C: Into<String>,
309 F: FnOnce() -> C,
310 {
311 self.add_context(context_fn())
312 }
313}
314
315macro_rules! implement_from {
316 ($source:path, $target:ident) => {
317 impl From<$source> for AsyncFusexError {
318 #[inline]
319 fn from(error: $source) -> Self {
320 Self::$target {
321 source: error,
322 context: vec![],
323 }
324 }
325 }
326 };
327}
328implement_from!(std::io::Error, IoErr);
329implement_from!(walkdir::Error, WalkdirErr);
330implement_from!(std::path::StripPrefixError, StripPrefixErr);
331implement_from!(nix::Error, NixErr);
332implement_from!(std::time::SystemTimeError, SystemTimeErr);
333implement_from!(tokio::task::JoinError, JoinErr);
334implement_from!(anyhow::Error, InternalErr);