Skip to main content

puffin/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::any::Any;
16use std::io::Error as IoError;
17use std::sync::Arc;
18
19use common_error::ext::{BoxedError, ErrorExt};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use snafu::{Location, Snafu};
23
24#[derive(Snafu)]
25#[snafu(visibility(pub))]
26#[stack_trace_debug]
27pub enum Error {
28    #[snafu(display("Failed to read"))]
29    Read {
30        #[snafu(source)]
31        error: IoError,
32        #[snafu(implicit)]
33        location: Location,
34    },
35
36    #[snafu(display("Failed to write"))]
37    Write {
38        #[snafu(source)]
39        error: IoError,
40        #[snafu(implicit)]
41        location: Location,
42    },
43
44    #[snafu(display("Failed to flush"))]
45    Flush {
46        #[snafu(source)]
47        error: IoError,
48        #[snafu(implicit)]
49        location: Location,
50    },
51
52    #[snafu(display("Failed to close"))]
53    Close {
54        #[snafu(source)]
55        error: IoError,
56        #[snafu(implicit)]
57        location: Location,
58    },
59
60    #[snafu(display("Failed to open"))]
61    Open {
62        #[snafu(source)]
63        error: IoError,
64        #[snafu(implicit)]
65        location: Location,
66    },
67
68    #[snafu(display("Failed to read metadata"))]
69    Metadata {
70        #[snafu(source)]
71        error: IoError,
72        #[snafu(implicit)]
73        location: Location,
74    },
75
76    #[snafu(display("Failed to create"))]
77    Create {
78        #[snafu(source)]
79        error: IoError,
80        #[snafu(implicit)]
81        location: Location,
82    },
83
84    #[snafu(display("Failed to rename"))]
85    Rename {
86        #[snafu(source)]
87        error: IoError,
88        #[snafu(implicit)]
89        location: Location,
90    },
91
92    #[snafu(display("Failed to remove"))]
93    Remove {
94        #[snafu(source)]
95        error: IoError,
96        #[snafu(implicit)]
97        location: Location,
98    },
99
100    #[snafu(display("Error while walking directory"))]
101    WalkDir {
102        #[snafu(source)]
103        error: async_walkdir::Error,
104        #[snafu(implicit)]
105        location: Location,
106    },
107
108    #[snafu(display("Magic not matched"))]
109    MagicNotMatched {
110        #[snafu(implicit)]
111        location: Location,
112    },
113
114    #[snafu(display("Unsupported decompression: {}", decompression))]
115    UnsupportedDecompression {
116        decompression: String,
117        #[snafu(implicit)]
118        location: Location,
119    },
120
121    #[snafu(display("Failed to serialize json"))]
122    SerializeJson {
123        #[snafu(source)]
124        error: serde_json::Error,
125        #[snafu(implicit)]
126        location: Location,
127    },
128
129    #[snafu(display("Failed to deserialize json"))]
130    DeserializeJson {
131        #[snafu(source)]
132        error: serde_json::Error,
133        #[snafu(implicit)]
134        location: Location,
135    },
136
137    #[snafu(display("Unexpected footer payload size: {}", size))]
138    UnexpectedFooterPayloadSize {
139        size: i32,
140        #[snafu(implicit)]
141        location: Location,
142    },
143
144    #[snafu(display("Invalid puffin footer"))]
145    InvalidPuffinFooter {
146        #[snafu(implicit)]
147        location: Location,
148    },
149
150    #[snafu(display(
151        "Unexpected puffin file size, min: {}, actual: {}",
152        min_file_size,
153        actual_file_size
154    ))]
155    UnexpectedPuffinFileSize {
156        min_file_size: u64,
157        actual_file_size: u64,
158        #[snafu(implicit)]
159        location: Location,
160    },
161
162    #[snafu(display("Failed to compress lz4"))]
163    Lz4Compression {
164        #[snafu(source)]
165        error: std::io::Error,
166
167        #[snafu(implicit)]
168        location: Location,
169    },
170
171    #[snafu(display("Failed to decompress lz4"))]
172    Lz4Decompression {
173        #[snafu(source)]
174        error: serde_json::Error,
175
176        #[snafu(implicit)]
177        location: Location,
178    },
179
180    #[snafu(display("Unsupported compression: {codec}"))]
181    UnsupportedCompression {
182        codec: String,
183        #[snafu(implicit)]
184        location: Location,
185    },
186
187    #[snafu(display("Write to the same blob twice: {blob}"))]
188    DuplicateBlob {
189        blob: String,
190        #[snafu(implicit)]
191        location: Location,
192    },
193
194    #[snafu(display("Multiple blobs have the same key: {blob}"))]
195    AmbiguousBlob {
196        blob: String,
197        #[snafu(implicit)]
198        location: Location,
199    },
200
201    #[snafu(display("Blob not found: {blob}"))]
202    BlobNotFound {
203        blob: String,
204        #[snafu(implicit)]
205        location: Location,
206    },
207
208    #[snafu(display("Blob index out of bound, index: {}, max index: {}", index, max_index))]
209    BlobIndexOutOfBound {
210        index: usize,
211        max_index: usize,
212        #[snafu(implicit)]
213        location: Location,
214    },
215
216    #[snafu(display("File key not match, expected: {}, actual: {}", expected, actual))]
217    FileKeyNotMatch {
218        expected: String,
219        actual: String,
220        #[snafu(implicit)]
221        location: Location,
222    },
223
224    #[snafu(display("Get value from cache"))]
225    CacheGet { source: Arc<Error> },
226
227    #[snafu(display("External error"))]
228    External {
229        #[snafu(source)]
230        error: BoxedError,
231        #[snafu(implicit)]
232        location: Location,
233    },
234}
235
236impl Error {
237    pub fn is_blob_not_found(&self) -> bool {
238        match self {
239            Error::BlobNotFound { .. } => true,
240            Error::CacheGet { source } => source.is_blob_not_found(),
241            _ => false,
242        }
243    }
244}
245
246impl ErrorExt for Error {
247    fn status_code(&self) -> StatusCode {
248        use Error::*;
249        match self {
250            Read { .. }
251            | MagicNotMatched { .. }
252            | DeserializeJson { .. }
253            | Write { .. }
254            | Flush { .. }
255            | Close { .. }
256            | Open { .. }
257            | Metadata { .. }
258            | Create { .. }
259            | Remove { .. }
260            | Rename { .. }
261            | SerializeJson { .. }
262            | UnexpectedFooterPayloadSize { .. }
263            | UnexpectedPuffinFileSize { .. }
264            | Lz4Compression { .. }
265            | Lz4Decompression { .. }
266            | AmbiguousBlob { .. }
267            | BlobNotFound { .. }
268            | BlobIndexOutOfBound { .. }
269            | FileKeyNotMatch { .. }
270            | WalkDir { .. }
271            | InvalidPuffinFooter { .. } => StatusCode::Unexpected,
272
273            UnsupportedCompression { .. } | UnsupportedDecompression { .. } => {
274                StatusCode::Unsupported
275            }
276
277            DuplicateBlob { .. } => StatusCode::InvalidArguments,
278
279            CacheGet { source } => source.status_code(),
280
281            External { error, .. } => error.status_code(),
282        }
283    }
284
285    fn as_any(&self) -> &dyn Any {
286        self
287    }
288}
289
290pub type Result<T> = std::result::Result<T, Error>;