1use std::{
2 cmp::PartialEq,
3 error::Error as StdError,
4 fmt::{self, Display},
5 io,
6};
7
8#[cfg(feature = "testing")]
9use backtrace::Backtrace;
10
11use crate::{
12 pagecache::{DiskPtr, PageView},
13 IVec,
14};
15
16pub type Result<T> = std::result::Result<T, Error>;
25
26pub(crate) type CasResult<'a, R> =
31 std::result::Result<PageView<'a>, Option<(PageView<'a>, R)>>;
32
33#[derive(Debug)]
36pub enum Error {
37 CollectionNotFound(IVec),
39 Unsupported(String),
41 ReportableBug(String),
43 Io(io::Error),
46 Corruption {
48 at: Option<DiskPtr>,
50 #[cfg(feature = "testing")]
52 bt: Backtrace,
53 #[cfg(not(feature = "testing"))]
55 bt: (),
56 },
57 #[doc(hidden)]
59 #[cfg(feature = "failpoints")]
60 FailPoint,
61}
62
63impl Error {
64 pub(crate) fn corruption(at: Option<DiskPtr>) -> Error {
65 Error::Corruption {
66 at,
67 #[cfg(feature = "testing")]
68 bt: Backtrace::new(),
69 #[cfg(not(feature = "testing"))]
70 bt: (),
71 }
72 }
73}
74
75impl Clone for Error {
76 fn clone(&self) -> Self {
77 use self::Error::*;
78
79 match self {
80 Io(ioe) => Io(io::Error::new(ioe.kind(), format!("{:?}", ioe))),
81 CollectionNotFound(name) => CollectionNotFound(name.clone()),
82 Unsupported(why) => Unsupported(why.clone()),
83 ReportableBug(what) => ReportableBug(what.clone()),
84 Corruption { at, bt } => Corruption { at: *at, bt: bt.clone() },
85 #[cfg(feature = "failpoints")]
86 FailPoint => FailPoint,
87 }
88 }
89}
90
91impl Eq for Error {}
92
93impl PartialEq for Error {
94 fn eq(&self, other: &Self) -> bool {
95 use self::Error::*;
96
97 match *self {
98 CollectionNotFound(ref l) => {
99 if let CollectionNotFound(ref r) = *other {
100 l == r
101 } else {
102 false
103 }
104 }
105 Unsupported(ref l) => {
106 if let Unsupported(ref r) = *other {
107 l == r
108 } else {
109 false
110 }
111 }
112 ReportableBug(ref l) => {
113 if let ReportableBug(ref r) = *other {
114 l == r
115 } else {
116 false
117 }
118 }
119 #[cfg(feature = "failpoints")]
120 FailPoint => {
121 if let FailPoint = *other {
122 true
123 } else {
124 false
125 }
126 }
127 Corruption { at: l, .. } => {
128 if let Corruption { at: r, .. } = *other {
129 l == r
130 } else {
131 false
132 }
133 }
134 Io(_) => false,
135 }
136 }
137}
138
139impl From<io::Error> for Error {
140 #[inline]
141 fn from(io_error: io::Error) -> Self {
142 Error::Io(io_error)
143 }
144}
145
146impl From<Error> for io::Error {
147 fn from(error: Error) -> io::Error {
148 use self::Error::*;
149 use std::io::ErrorKind;
150 match error {
151 Io(ioe) => ioe,
152 CollectionNotFound(name) =>
153 io::Error::new(
154 ErrorKind::NotFound,
155 format!("collection not found: {:?}", name),
156 ),
157 Unsupported(why) => io::Error::new(
158 ErrorKind::InvalidInput,
159 format!("operation not supported: {:?}", why),
160 ),
161 ReportableBug(what) => io::Error::new(
162 ErrorKind::Other,
163 format!("unexpected bug! please report this bug at <github.rs/spacejam/sled>: {:?}", what),
164 ),
165 Corruption { .. } => io::Error::new(
166 ErrorKind::InvalidData,
167 format!("corruption encountered: {:?}", error),
168 ),
169 #[cfg(feature = "failpoints")]
170 FailPoint => io::Error::new(
171 ErrorKind::Other,
172 "failpoint"
173 ),
174 }
175 }
176}
177
178impl StdError for Error {}
179
180impl Display for Error {
181 fn fmt(
182 &self,
183 f: &mut fmt::Formatter<'_>,
184 ) -> std::result::Result<(), fmt::Error> {
185 use self::Error::*;
186
187 match *self {
188 CollectionNotFound(ref name) => {
189 write!(f, "Collection {:?} does not exist", name,)
190 }
191 Unsupported(ref e) => write!(f, "Unsupported: {}", e),
192 ReportableBug(ref e) => write!(
193 f,
194 "Unexpected bug has happened: {}. \
195 PLEASE REPORT THIS BUG!",
196 e
197 ),
198 #[cfg(feature = "failpoints")]
199 FailPoint => write!(f, "Fail point has been triggered."),
200 Io(ref e) => write!(f, "IO error: {}", e),
201 Corruption { at, ref bt } => write!(
202 f,
203 "Read corrupted data at file offset {:?} backtrace {:?}",
204 at, bt
205 ),
206 }
207 }
208}