Files
reth/crates/storage/errors/src/db.rs
0xAtreides 7e60bc4dae feature: loglevel value parser (#8573)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
2024-06-05 07:58:26 +00:00

186 lines
5.7 KiB
Rust

use std::{fmt::Display, str::FromStr};
use thiserror::Error;
/// Database error type.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum DatabaseError {
/// Failed to open the database.
#[error("failed to open the database: {0}")]
Open(DatabaseErrorInfo),
/// Failed to create a table in the database.
#[error("failed to create a table: {0}")]
CreateTable(DatabaseErrorInfo),
/// Failed to write a value into a table.
#[error(transparent)]
Write(#[from] Box<DatabaseWriteError>),
/// Failed to read a value from a table.
#[error("failed to read a value from a database table: {0}")]
Read(DatabaseErrorInfo),
/// Failed to delete a `(key, value)` pair from a table.
#[error("database delete error code: {0}")]
Delete(DatabaseErrorInfo),
/// Failed to commit transaction changes into the database.
#[error("failed to commit transaction changes: {0}")]
Commit(DatabaseErrorInfo),
/// Failed to initiate a transaction.
#[error("failed to initialize a transaction: {0}")]
InitTx(DatabaseErrorInfo),
/// Failed to initialize a cursor.
#[error("failed to initialize a cursor: {0}")]
InitCursor(DatabaseErrorInfo),
/// Failed to decode a key from a table.
#[error("failed to decode a key from a table")]
Decode,
/// Failed to get database stats.
#[error("failed to get stats: {0}")]
Stats(DatabaseErrorInfo),
/// Failed to use the specified log level, as it's not available.
#[error("log level {0:?} is not available")]
LogLevelUnavailable(LogLevel),
/// Other unspecified error.
#[error("{0}")]
Other(String),
}
/// Common error struct to propagate implementation-specific error information.
#[derive(Debug, Error, Clone, PartialEq, Eq)]
#[error("{message} ({code})")]
pub struct DatabaseErrorInfo {
/// Human-readable error message.
pub message: String,
/// Error code.
pub code: i32,
}
impl<E> From<E> for DatabaseErrorInfo
where
E: Display + Into<i32>,
{
#[inline]
fn from(value: E) -> Self {
Self { message: value.to_string(), code: value.into() }
}
}
impl From<DatabaseWriteError> for DatabaseError {
#[inline]
fn from(value: DatabaseWriteError) -> Self {
Self::Write(Box::new(value))
}
}
/// Database write error.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
#[error(
"write operation {operation:?} failed for key \"{key}\" in table {table_name:?}: {info}",
key = reth_primitives::hex::encode(key),
)]
pub struct DatabaseWriteError {
/// The error code and message.
pub info: DatabaseErrorInfo,
/// The write operation type.
pub operation: DatabaseWriteOperation,
/// The table name.
pub table_name: &'static str,
/// The write key.
pub key: Vec<u8>,
}
/// Database write operation type.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DatabaseWriteOperation {
/// Append cursor.
CursorAppend,
/// Upsert cursor.
CursorUpsert,
/// Insert cursor.
CursorInsert,
/// Append duplicate cursor.
CursorAppendDup,
/// Put.
Put,
}
/// Database log level.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum LogLevel {
/// Enables logging for critical conditions, i.e. assertion failures.
Fatal,
/// Enables logging for error conditions.
Error,
/// Enables logging for warning conditions.
Warn,
/// Enables logging for normal but significant condition.
Notice,
/// Enables logging for verbose informational.
Verbose,
/// Enables logging for debug-level messages.
Debug,
/// Enables logging for trace debug-level messages.
Trace,
/// Enables logging for extra debug-level messages.
Extra,
}
impl LogLevel {
/// All possible variants of the `LogLevel` enum
pub const fn value_variants() -> &'static [Self] {
&[
Self::Fatal,
Self::Error,
Self::Warn,
Self::Notice,
Self::Verbose,
Self::Debug,
Self::Trace,
Self::Extra,
]
}
/// Static str reference to `LogLevel` enum, required for `Clap::Builder::PossibleValue::new()`
pub const fn variant_name(&self) -> &'static str {
match self {
Self::Fatal => "fatal",
Self::Error => "error",
Self::Warn => "warn",
Self::Notice => "notice",
Self::Verbose => "verbose",
Self::Debug => "debug",
Self::Trace => "trace",
Self::Extra => "extra",
}
}
/// Returns all variants descriptions
pub const fn help_message(&self) -> &'static str {
match self {
Self::Fatal => "Enables logging for critical conditions, i.e. assertion failures",
Self::Error => "Enables logging for error conditions",
Self::Warn => "Enables logging for warning conditions",
Self::Notice => "Enables logging for normal but significant condition",
Self::Verbose => "Enables logging for verbose informational",
Self::Debug => "Enables logging for debug-level messages",
Self::Trace => "Enables logging for trace debug-level messages",
Self::Extra => "Enables logging for extra debug-level messages",
}
}
}
impl FromStr for LogLevel {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"fatal" => Ok(Self::Fatal),
"error" => Ok(Self::Error),
"warn" => Ok(Self::Warn),
"notice" => Ok(Self::Notice),
"verbose" => Ok(Self::Verbose),
"debug" => Ok(Self::Debug),
"trace" => Ok(Self::Trace),
"extra" => Ok(Self::Extra),
_ => Err(format!("Invalid log level: {}", s)),
}
}
}