Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(reth-storage-errors): no_std support #10011

Merged
merged 11 commits into from
Aug 13, 2024
2 changes: 1 addition & 1 deletion Cargo.lock

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

5 changes: 3 additions & 2 deletions crates/storage/errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ alloy-rlp.workspace = true
reth-primitives.workspace = true
reth-fs-util.workspace = true

thiserror-no-std = { workspace = true, default-features = false }
# misc
derive_more.workspace = true

[features]
default = ["std"]
std = ["thiserror-no-std/std"]
std = []
80 changes: 52 additions & 28 deletions crates/storage/errors/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "std")]
use std::{fmt::Display, str::FromStr, string::String};
use std::{fmt, fmt::Display, str::FromStr, string::String};

#[cfg(not(feature = "std"))]
use alloc::{
Expand All @@ -8,54 +8,66 @@ use alloc::{
string::{String, ToString},
vec::Vec,
};

#[cfg(not(feature = "std"))]
use core::{fmt::Display, str::FromStr};
use core::{
fmt,
fmt::{Debug, Display},
str::FromStr,
};

/// Database error type.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::Error)]
#[derive(Clone, Debug, PartialEq, Eq, derive_more::Display)]
pub enum DatabaseError {
/// Failed to open the database.
#[error("failed to open the database: {0}")]
#[display(fmt = "failed to open the database: {_0}")]
Open(DatabaseErrorInfo),
/// Failed to create a table in the database.
#[error("failed to create a table: {0}")]
#[display(fmt = "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}")]
#[display(fmt = "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}")]
#[display(fmt = "database delete error code: {_0}")]
Delete(DatabaseErrorInfo),
/// Failed to commit transaction changes into the database.
#[error("failed to commit transaction changes: {0}")]
#[display(fmt = "failed to commit transaction changes: {_0}")]
Commit(DatabaseErrorInfo),
/// Failed to initiate a transaction.
#[error("failed to initialize a transaction: {0}")]
#[display(fmt = "failed to initialize a transaction: {_0}")]
InitTx(DatabaseErrorInfo),
/// Failed to initialize a cursor.
#[error("failed to initialize a cursor: {0}")]
#[display(fmt = "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")]
#[display(fmt = "failed to decode a key from a table")]
Decode,
/// Failed to get database stats.
#[error("failed to get stats: {0}")]
#[display(fmt = "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")]
#[display(fmt = "log level {_0:?} is not available")]
LogLevelUnavailable(LogLevel),
/// Other unspecified error.
#[error("{0}")]
#[display(fmt = "{_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) => std::error::Error::source(err),
_ => Option::None,
}
}
}

/// Common error struct to propagate implementation-specific error information.
#[derive(Debug, Clone, PartialEq, Eq, thiserror_no_std::Error)]
#[error("{message} ({code})")]
#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
#[display(fmt = "{message} ({code})")]
pub struct DatabaseErrorInfo {
/// Human-readable error message.
pub message: String,
Expand All @@ -68,24 +80,20 @@ where
E: Display + Into<i32>,
{
#[inline]
fn from(value: E) -> Self {
Self { message: value.to_string(), code: value.into() }
fn from(error: E) -> Self {
Self { message: error.to_string(), code: error.into() }
}
}

impl From<DatabaseWriteError> for DatabaseError {
#[inline]
fn from(value: DatabaseWriteError) -> Self {
Self::Write(Box::new(value))
fn from(error: DatabaseWriteError) -> Self {
Self::Write(Box::new(error))
}
}

/// Database write error.
#[derive(Clone, Debug, PartialEq, Eq, thiserror_no_std::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 @@ -97,6 +105,22 @@ pub struct DatabaseWriteError {
pub key: Vec<u8>,
}

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

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

/// Database write operation type.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DatabaseWriteOperation {
Expand Down
15 changes: 10 additions & 5 deletions crates/storage/errors/src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@ use reth_fs_util::FsPathError;
use alloc::string::{String, ToString};

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

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

/// TODO: turn into variant once `ProviderError`
impl From<FsPathError> for StorageLockError {
fn from(source: FsPathError) -> Self {
Self::Other(source.to_string())
fn from(error: FsPathError) -> Self {
Self::Other(error.to_string())
}
}
Loading