parity_db/
error.rs

1// Copyright 2021-2022 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or MIT.
3
4use 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;