use std::{
cmp::PartialEq,
error::Error as StdError,
fmt::{self, Display},
io,
};
#[cfg(feature = "testing")]
use backtrace::Backtrace;
use crate::{
pagecache::{DiskPtr, PageView},
IVec,
};
pub type Result<T> = std::result::Result<T, Error>;
pub(crate) type CasResult<'a, R> =
std::result::Result<PageView<'a>, Option<(PageView<'a>, R)>>;
#[derive(Debug)]
pub enum Error {
CollectionNotFound(IVec),
Unsupported(String),
ReportableBug(String),
Io(io::Error),
Corruption {
at: Option<DiskPtr>,
#[cfg(feature = "testing")]
bt: Backtrace,
#[cfg(not(feature = "testing"))]
bt: (),
},
#[doc(hidden)]
#[cfg(feature = "failpoints")]
FailPoint,
}
impl Error {
pub(crate) fn corruption(at: Option<DiskPtr>) -> Error {
Error::Corruption {
at,
#[cfg(feature = "testing")]
bt: Backtrace::new(),
#[cfg(not(feature = "testing"))]
bt: (),
}
}
}
impl Clone for Error {
fn clone(&self) -> Self {
use self::Error::*;
match self {
Io(ioe) => Io(io::Error::new(ioe.kind(), format!("{:?}", ioe))),
CollectionNotFound(name) => CollectionNotFound(name.clone()),
Unsupported(why) => Unsupported(why.clone()),
ReportableBug(what) => ReportableBug(what.clone()),
Corruption { at, bt } => Corruption { at: *at, bt: bt.clone() },
#[cfg(feature = "failpoints")]
FailPoint => FailPoint,
}
}
}
impl Eq for Error {}
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
use self::Error::*;
match *self {
CollectionNotFound(ref l) => {
if let CollectionNotFound(ref r) = *other {
l == r
} else {
false
}
}
Unsupported(ref l) => {
if let Unsupported(ref r) = *other {
l == r
} else {
false
}
}
ReportableBug(ref l) => {
if let ReportableBug(ref r) = *other {
l == r
} else {
false
}
}
#[cfg(feature = "failpoints")]
FailPoint => {
if let FailPoint = *other {
true
} else {
false
}
}
Corruption { at: l, .. } => {
if let Corruption { at: r, .. } = *other {
l == r
} else {
false
}
}
Io(_) => false,
}
}
}
impl From<io::Error> for Error {
#[inline]
fn from(io_error: io::Error) -> Self {
Error::Io(io_error)
}
}
impl From<Error> for io::Error {
fn from(error: Error) -> io::Error {
use self::Error::*;
use std::io::ErrorKind;
match error {
Io(ioe) => ioe,
CollectionNotFound(name) =>
io::Error::new(
ErrorKind::NotFound,
format!("collection not found: {:?}", name),
),
Unsupported(why) => io::Error::new(
ErrorKind::InvalidInput,
format!("operation not supported: {:?}", why),
),
ReportableBug(what) => io::Error::new(
ErrorKind::Other,
format!("unexpected bug! please report this bug at <github.rs/spacejam/sled>: {:?}", what),
),
Corruption { .. } => io::Error::new(
ErrorKind::InvalidData,
format!("corruption encountered: {:?}", error),
),
#[cfg(feature = "failpoints")]
FailPoint => io::Error::new(
ErrorKind::Other,
"failpoint"
),
}
}
}
impl StdError for Error {}
impl Display for Error {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> std::result::Result<(), fmt::Error> {
use self::Error::*;
match *self {
CollectionNotFound(ref name) => {
write!(f, "Collection {:?} does not exist", name,)
}
Unsupported(ref e) => write!(f, "Unsupported: {}", e),
ReportableBug(ref e) => write!(
f,
"Unexpected bug has happened: {}. \
PLEASE REPORT THIS BUG!",
e
),
#[cfg(feature = "failpoints")]
FailPoint => write!(f, "Fail point has been triggered."),
Io(ref e) => write!(f, "IO error: {}", e),
Corruption { at, ref bt } => write!(
f,
"Read corrupted data at file offset {:?} backtrace {:?}",
at, bt
),
}
}
}