1use crate::column::ColId;
5#[cfg(feature = "instrumentation")]
6use std::sync::atomic::{AtomicUsize, Ordering};
7use std::{fmt, io, sync::Arc};
8
9pub type Result<T> = std::result::Result<T, Error>;
10
11#[derive(Debug)]
12pub enum Error {
13 Io(io::Error),
14 Corruption(String),
15 InvalidConfiguration(String),
16 IncompatibleColumnConfig { id: ColId, reason: String },
17 InvalidInput(String),
18 InvalidValueData,
19 Background(Arc<Error>),
20 Locked(io::Error),
21 Migration(String),
22 Compression,
23 DatabaseNotFound,
24}
25
26impl fmt::Display for Error {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 Error::Io(e) => write!(f, "IO Error: {e}"),
30 Error::Corruption(e) => write!(f, "Corruption: {e}"),
31 Error::InvalidConfiguration(e) => write!(f, "Invalid configuration: {e}"),
32 Error::IncompatibleColumnConfig { id, reason } => {
33 write!(f, "Invalid column {id} configuration : {reason}")
34 },
35 Error::InvalidInput(e) => write!(f, "Invalid input: {e}"),
36 Error::InvalidValueData => write!(f, "Invalid data in value table"),
37 Error::Background(e) => write!(f, "Background worker error: {e}"),
38 Error::Locked(e) => write!(f, "Database file is in use. ({e})"),
39 Error::Migration(e) => write!(f, "Migration error: {e}"),
40 Error::Compression => write!(f, "Compression error"),
41 Error::DatabaseNotFound => write!(f, "Database does not exist"),
42 }
43 }
44}
45
46impl std::error::Error for Error {
47 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
48 match self {
49 Error::Io(e) => Some(e),
50 Error::Background(e) => e.source(),
51 Error::Locked(e) => Some(e),
52 _ => None,
53 }
54 }
55}
56
57#[cfg(feature = "instrumentation")]
58thread_local! {
59 pub static IO_COUNTER_BEFORE_ERROR: AtomicUsize = AtomicUsize::new(usize::MAX);
60}
61
62#[cfg(feature = "instrumentation")]
63pub fn set_number_of_allowed_io_operations(val: usize) {
64 IO_COUNTER_BEFORE_ERROR.with(|v| v.store(val, Ordering::Relaxed));
65}
66
67#[cfg(feature = "instrumentation")]
68macro_rules! try_io {
69 ($e:expr) => {{
70 if crate::error::IO_COUNTER_BEFORE_ERROR.with(|value| {
71 value
72 .fetch_update(
73 ::std::sync::atomic::Ordering::SeqCst,
74 ::std::sync::atomic::Ordering::SeqCst,
75 |v| Some(v.saturating_sub(1)),
76 )
77 .unwrap()
78 }) == 0
79 {
80 Err(crate::error::Error::Io(::std::io::Error::new(
81 ::std::io::ErrorKind::Other,
82 "Instrumented failure",
83 )))?
84 } else {
85 $e.map_err(crate::error::Error::Io)?
86 }
87 }};
88}
89
90#[cfg(not(feature = "instrumentation"))]
91macro_rules! try_io {
92 ($e:expr) => {{
93 $e.map_err(crate::error::Error::Io)?
94 }};
95}
96
97pub(crate) use try_io;