Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/storage/errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ workspace = true
reth-primitives.workspace = true
reth-fs-util.workspace = true

thiserror.workspace = true

[features]
default = ["std"]
std = []
88 changes: 64 additions & 24 deletions crates/storage/errors/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,57 +1,77 @@
use std::{fmt::Display, str::FromStr};
use thiserror::Error;
use alloc::{boxed::Box, format, string::String, vec::Vec};
use core::{
fmt::{Display, Formatter, Result},
str::FromStr,
};

/// Database error type.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
#[derive(Clone, Debug, PartialEq, Eq)]
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>),
Write(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),
}

#[cfg(feature = "std")]
impl std::error::Error for DatabaseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Write(err) => Some(&**err),
_ => None,
}
}
}

impl Display for DatabaseError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
Self::Open(info) => write!(f, "failed to open the database: {}", info),
Self::CreateTable(info) => write!(f, "failed to create a table: {}", info),
Self::Write(err) => write!(f, "{}", err),
Self::Read(info) => write!(f, "failed to read a value from a database table: {}", info),
Self::Delete(info) => write!(f, "database delete error code: {}", info),
Self::Commit(info) => write!(f, "failed to commit transaction changes: {}", info),
Self::InitTx(info) => write!(f, "failed to initialize a transaction: {}", info),
Self::InitCursor(info) => write!(f, "failed to initialize a cursor: {}", info),
Self::Decode => write!(f, "failed to decode a key from a table"),
Self::Stats(info) => write!(f, "failed to get stats: {}", info),
Self::LogLevelUnavailable(level) => write!(f, "log level {:?} is not available", level),
Self::Other(msg) => write!(f, "{}", msg),
}
}
}

/// Common error struct to propagate implementation-specific error information.
#[derive(Debug, Error, Clone, PartialEq, Eq)]
#[error("{message} ({code})")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DatabaseErrorInfo {
/// Human-readable error message.
pub message: String,
/// Error code.
pub code: i32,
}

#[cfg(feature = "std")]
impl<E> From<E> for DatabaseErrorInfo
where
E: Display + Into<i32>,
Expand All @@ -69,12 +89,16 @@ impl From<DatabaseWriteError> for DatabaseError {
}
}

#[cfg(feature = "std")]
impl std::error::Error for DatabaseErrorInfo {}

impl Display for DatabaseErrorInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "{} ({})", self.message, self.code)
}
}
/// 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),
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DatabaseWriteError {
/// The error code and message.
pub info: DatabaseErrorInfo,
Expand All @@ -101,6 +125,22 @@ pub enum DatabaseWriteOperation {
Put,
}

#[cfg(feature = "std")]
impl std::error::Error for DatabaseWriteError {}

impl Display for DatabaseWriteError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(
f,
"write operation {:?} failed for key \"{}\" in table {:?}: {}",
self.operation,
reth_primitives::hex::encode(&self.key),
self.table_name,
self.info
)
}
}

/// Database log level.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum LogLevel {
Expand Down Expand Up @@ -169,7 +209,7 @@ impl LogLevel {
impl FromStr for LogLevel {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"fatal" => Ok(Self::Fatal),
"error" => Ok(Self::Error),
Expand Down
3 changes: 3 additions & 0 deletions crates/storage/errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

/// Database error
pub mod db;
Expand Down
23 changes: 19 additions & 4 deletions crates/storage/errors/src/lockfile.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use alloc::string::{String, ToString};
use core::fmt::{Display, Formatter, Result};
use reth_fs_util::FsPathError;
use thiserror::Error;

#[derive(Error, Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
/// Storage lock error.
pub enum StorageLockError {
/// Write lock taken
#[error("storage directory is currently in use as read-write by another process: PID {0}")]
Taken(usize),
/// Indicates other unspecified errors.
#[error("{0}")]
Other(String),
}

Expand All @@ -18,3 +17,19 @@ impl From<FsPathError> for StorageLockError {
Self::Other(source.to_string())
}
}

#[cfg(feature = "std")]
impl std::error::Error for StorageLockError {}

impl Display for StorageLockError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
Self::Taken(write_lock) => write!(
f,
"storage directory is currently in use as read-write by another process: PID {}",
write_lock
),
Self::Other(unspecified) => write!(f, "{}", unspecified),
}
}
}
Loading