Skip to main content

dragonfly_client_core/error/
mod.rs

1/*
2 *     Copyright 2024 The Dragonfly Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17pub mod errors;
18pub mod message;
19
20pub use errors::ErrorType;
21pub use errors::ExternalError;
22
23pub use errors::OrErr;
24pub use errors::{BackendError, DownloadFromParentFailed};
25
26/// The error for dragonfly.
27#[derive(thiserror::Error, Debug)]
28pub enum DFError {
29    /// The error for IO operation.
30    #[error(transparent)]
31    IO(#[from] std::io::Error),
32
33    /// The error for environment variable.
34    #[error(transparent)]
35    VarError(#[from] std::env::VarError),
36
37    /// The error for send.
38    #[error("mpsc send: {0}")]
39    MpscSend(String),
40
41    /// The error for send timeout.
42    #[error("send timeout")]
43    SendTimeout,
44
45    /// The error for hashring.
46    #[error{"hashring {0} is failed"}]
47    HashRing(String),
48
49    /// The error when there is no space left on device.
50    #[error("no space left on device: {0}")]
51    NoSpace(String),
52
53    /// The error when the host is not found.
54    #[error{"host {0} not found"}]
55    HostNotFound(String),
56
57    /// The error when the task is not found.
58    #[error{"task {0} not found"}]
59    TaskNotFound(String),
60
61    /// The error when the piece is not found.
62    #[error{"piece {0} not found"}]
63    PieceNotFound(String),
64
65    /// The error when the piece state is failed.
66    #[error{"piece {0} state is failed"}]
67    PieceStateIsFailed(String),
68
69    /// The error when the download piece finished timeout.
70    #[error{"download piece {0} finished timeout"}]
71    DownloadPieceFinishedTimeout(String),
72
73    /// The error when the wait for piece finished timeout.
74    #[error{"wait for piece {0} finished timeout"}]
75    WaitForPieceFinishedTimeout(String),
76
77    /// The error when the available manager is not found.
78    #[error{"available manager not found"}]
79    AvailableManagerNotFound,
80
81    /// The error when the available schedulers is not found.
82    #[error{"available schedulers not found"}]
83    AvailableSchedulersNotFound,
84
85    /// The error when the download from parent is failed.
86    #[error(transparent)]
87    DownloadFromParentFailed(DownloadFromParentFailed),
88
89    /// The error when the column family is not found.
90    #[error{"column family {0} not found"}]
91    ColumnFamilyNotFound(String),
92
93    /// The error when the state transition is invalid.
94    #[error{"can not transit from {0} to {1}"}]
95    InvalidStateTransition(String, String),
96
97    /// The error when the state is invalid.
98    #[error{"invalid state {0}"}]
99    InvalidState(String),
100
101    /// The error when the uri is invalid.
102    #[error("invalid uri {0}")]
103    InvalidURI(String),
104
105    /// The error when the peer is invalid.
106    #[error("invalid peer {0}")]
107    InvalidPeer(String),
108
109    /// The error when the scheduler client is not found.
110    #[error{"scheduler client not found"}]
111    SchedulerClientNotFound,
112
113    /// The error when the response is unexpected.
114    #[error{"unexpected response"}]
115    UnexpectedResponse,
116
117    /// The error when the digest is mismatch.
118    #[error{"digest mismatch expected: {0}, actual: {1}"}]
119    DigestMismatch(String, String),
120
121    /// The error when the content length is mismatch.
122    #[error("content length mismatch expected: {0}, actual: {1}")]
123    ContentLengthMismatch(u64, u64),
124
125    /// The error when the max schedule count is exceeded.
126    #[error("max schedule count {0} exceeded")]
127    MaxScheduleCountExceeded(u32),
128
129    /// The error when the content length is invalid.
130    #[error("invalid content length")]
131    InvalidContentLength,
132
133    /// The error when the piece length is invalid.
134    #[error("invalid piece length")]
135    InvalidPieceLength,
136
137    /// The error when the parameter is invalid.
138    #[error("invalid parameter")]
139    InvalidParameter,
140
141    /// The error for net address parse.
142    #[error(transparent)]
143    NetAddrParseError(#[from] std::net::AddrParseError),
144
145    /// The error for infallible.
146    #[error(transparent)]
147    ConvertInfallible(#[from] std::convert::Infallible),
148
149    /// The error for utf8.
150    #[error(transparent)]
151    Utf8(#[from] std::str::Utf8Error),
152
153    /// The error when the mutex is poisoned.
154    #[error("mutex poisoned: {0}")]
155    MutexPoisoned(String),
156
157    /// The error when the error is unknown.
158    #[error("unknown {0}")]
159    Unknown(String),
160
161    /// The error when the feature is not implemented.
162    #[error{"unimplemented"}]
163    Unimplemented,
164
165    /// The error when the permission is denied.
166    #[error{"permission denied"}]
167    PermissionDenied,
168
169    /// The error when the range fallback error is empty.
170    #[error{"RangeUnsatisfiable: Failed to parse range fallback error, please file an issue"}]
171    EmptyHTTPRangeError,
172
173    /// The error for unauthorized.
174    #[error{"unauthorized"}]
175    Unauthorized,
176
177    /// The error for array try from slice.
178    #[error(transparent)]
179    ArrayTryFromSliceError(#[from] std::array::TryFromSliceError),
180
181    /// The error for vortex protocol status.
182    #[error("vortex protocol status: code={0:?}, message={1}")]
183    VortexProtocolStatus(vortex_protocol::tlv::error::Code, String),
184
185    /// The error for vortex protocol.
186    #[error(transparent)]
187    VortexProtocolError(#[from] vortex_protocol::error::Error),
188
189    /// The error for tonic status.
190    #[error(transparent)]
191    TonicStatus(#[from] tonic::Status),
192
193    /// The error for tonic transport.
194    #[error(transparent)]
195    TonicTransportError(#[from] tonic::transport::Error),
196
197    /// The error for tonic reflection server.
198    #[error(transparent)]
199    TonicReflectionServerError(#[from] tonic_reflection::server::Error),
200
201    /// The error for tonic stream elapsed.
202    #[error(transparent)]
203    TokioStreamElapsed(#[from] tokio_stream::Elapsed),
204
205    // TokioTimeErrorElapsed is the error for tokio time elapsed.
206    #[error(transparent)]
207    TokioTimeErrorElapsed(#[from] tokio::time::error::Elapsed),
208
209    /// The error for headers.
210    #[error(transparent)]
211    HeadersError(#[from] headers::Error),
212
213    // InvalidHeaderName is the error for invalid header name.
214    #[error(transparent)]
215    HTTTHeaderInvalidHeaderName(#[from] http::header::InvalidHeaderName),
216
217    // InvalidHeaderValue is the error for invalid header value.
218    #[error(transparent)]
219    HTTTHeaderInvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
220
221    // HTTTHeaderToStrError is the error for header to str.
222    #[error(transparent)]
223    HTTTHeaderToStrError(#[from] http::header::ToStrError),
224
225    /// The error for url parse.
226    #[error(transparent)]
227    URLParseError(#[from] url::ParseError),
228
229    /// The error for reqwest.
230    #[error(transparent)]
231    ReqwestError(#[from] reqwest::Error),
232
233    /// The error for reqwest middleware.
234    #[error(transparent)]
235    ReqwestMiddlewareError(#[from] reqwest_middleware::Error),
236
237    /// The error for opendal.
238    #[error(transparent)]
239    OpenDALError(#[from] opendal::Error),
240
241    /// The error for hyper.
242    #[error(transparent)]
243    HyperError(#[from] hyper::Error),
244
245    /// The error for backend.
246    #[error(transparent)]
247    BackendError(Box<BackendError>),
248
249    /// The error for hyper util client legacy.
250    #[error(transparent)]
251    HyperUtilClientLegacyError(#[from] hyper_util::client::legacy::Error),
252
253    /// The error for external error.
254    #[error(transparent)]
255    ExternalError(#[from] ExternalError),
256
257    /// The error for max download files exceeded.
258    #[error(
259        "exceeded the maximum download limit of {0} files. Use --max-files to increase this limit"
260    )]
261    MaxDownloadFilesExceeded(usize),
262
263    /// The error for unsupported.
264    #[error("unsupported {0}")]
265    Unsupported(String),
266
267    /// The error for tokio join.
268    #[error(transparent)]
269    TokioJoinError(tokio::task::JoinError),
270
271    /// The error for validate.
272    #[error("validate failed: {0}")]
273    ValidationError(String),
274
275    /// The error for cgroups fs.
276    #[cfg(target_os = "linux")]
277    #[error(transparent)]
278    CgroupsFSError(#[from] cgroups_rs::fs::error::Error),
279}
280
281/// The error for send.
282impl<T> From<tokio::sync::mpsc::error::SendError<T>> for DFError {
283    fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
284        Self::MpscSend(e.to_string())
285    }
286}
287
288/// The error for mutex poisoned.
289impl<T> From<std::sync::PoisonError<T>> for DFError {
290    fn from(e: std::sync::PoisonError<T>) -> Self {
291        Self::MutexPoisoned(e.to_string())
292    }
293}
294
295/// The error for send timeout.
296impl<T> From<tokio::sync::mpsc::error::SendTimeoutError<T>> for DFError {
297    fn from(err: tokio::sync::mpsc::error::SendTimeoutError<T>) -> Self {
298        match err {
299            tokio::sync::mpsc::error::SendTimeoutError::Timeout(_) => Self::SendTimeout,
300            tokio::sync::mpsc::error::SendTimeoutError::Closed(_) => Self::SendTimeout,
301        }
302    }
303}
304
305#[cfg(test)]
306mod tests {
307    use super::*;
308
309    #[test]
310    fn should_convert_externalerror_to_dferror() {
311        fn function_return_inner_error() -> Result<(), std::io::Error> {
312            let inner_error = std::io::Error::other("inner error");
313            Err(inner_error)
314        }
315
316        fn do_sth_with_error() -> Result<(), DFError> {
317            function_return_inner_error().map_err(|err| {
318                ExternalError::new(crate::error::ErrorType::StorageError).with_cause(err.into())
319            })?;
320            Ok(())
321        }
322
323        let err = do_sth_with_error().err().unwrap();
324        assert_eq!(format!("{err}"), "StorageError cause: inner error");
325    }
326}