1use alloc::{
2 boxed::Box,
3 format,
4 string::{String, ToString},
5 sync::Arc,
6 vec::Vec,
7};
8use core::{
9 error::Error,
10 fmt::{Debug, Display},
11 str::FromStr,
12};
13use reth_codecs::DecompressError;
14
15#[derive(Clone, Debug, thiserror::Error)]
17pub enum DatabaseError {
18 #[error("failed to open the database: {_0}")]
20 Open(DatabaseErrorInfo),
21 #[error("failed to create a table: {_0}")]
23 CreateTable(DatabaseErrorInfo),
24 #[error(transparent)]
26 Write(Box<DatabaseWriteError>),
27 #[error("failed to read a value from a database table: {_0}")]
29 Read(DatabaseErrorInfo),
30 #[error("database delete error code: {_0}")]
32 Delete(DatabaseErrorInfo),
33 #[error("failed to commit transaction changes: {_0}")]
35 Commit(DatabaseErrorInfo),
36 #[error("failed to initialize a transaction: {_0}")]
38 InitTx(DatabaseErrorInfo),
39 #[error("failed to initialize a cursor: {_0}")]
41 InitCursor(DatabaseErrorInfo),
42 #[error("failed to decode a key from a table")]
44 Decode,
45 #[error("failed to get stats: {_0}")]
47 Stats(DatabaseErrorInfo),
48 #[error("log level {_0:?} is not available")]
50 LogLevelUnavailable(LogLevel),
51 #[error("{_0}")]
53 Other(String),
54 #[error(transparent)]
56 Custom(#[from] Arc<dyn Error + Send + Sync>),
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
61#[display("{message} ({code})")]
62pub struct DatabaseErrorInfo {
63 pub message: Box<str>,
65 pub code: i32,
67}
68
69impl<E> From<E> for DatabaseErrorInfo
70where
71 E: Display + Into<i32>,
72{
73 #[inline]
74 fn from(error: E) -> Self {
75 Self { message: error.to_string().into(), code: error.into() }
76 }
77}
78
79impl From<DatabaseWriteError> for DatabaseError {
80 #[inline]
81 fn from(error: DatabaseWriteError) -> Self {
82 Self::Write(Box::new(error))
83 }
84}
85
86impl From<reth_codecs::DecompressError> for DatabaseError {
87 #[inline]
88 fn from(_: DecompressError) -> Self {
89 Self::Decode
90 }
91}
92
93#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
95#[error("write operation {:?} failed for key \"{}\" in table {}: {}",
96 self.operation,
97 alloy_primitives::hex::encode(&self.key),
98 self.table_name,
99 self.info)]
100pub struct DatabaseWriteError {
101 pub info: DatabaseErrorInfo,
103 pub operation: DatabaseWriteOperation,
105 pub table_name: &'static str,
107 pub key: Vec<u8>,
109}
110
111#[derive(Clone, Copy, Debug, PartialEq, Eq)]
113pub enum DatabaseWriteOperation {
114 CursorAppend,
116 CursorUpsert,
118 CursorInsert,
120 CursorAppendDup,
122 PutUpsert,
124 PutAppend,
126 Flush,
128}
129
130#[derive(Debug, PartialEq, Eq, Clone, Copy)]
132pub enum LogLevel {
133 Fatal,
135 Error,
137 Warn,
139 Notice,
141 Verbose,
143 Debug,
145 Trace,
147 Extra,
149}
150
151impl LogLevel {
152 pub const fn value_variants() -> &'static [Self] {
154 &[
155 Self::Fatal,
156 Self::Error,
157 Self::Warn,
158 Self::Notice,
159 Self::Verbose,
160 Self::Debug,
161 Self::Trace,
162 Self::Extra,
163 ]
164 }
165
166 pub const fn variant_name(&self) -> &'static str {
168 match self {
169 Self::Fatal => "fatal",
170 Self::Error => "error",
171 Self::Warn => "warn",
172 Self::Notice => "notice",
173 Self::Verbose => "verbose",
174 Self::Debug => "debug",
175 Self::Trace => "trace",
176 Self::Extra => "extra",
177 }
178 }
179
180 pub const fn help_message(&self) -> &'static str {
182 match self {
183 Self::Fatal => "Enables logging for critical conditions, i.e. assertion failures",
184 Self::Error => "Enables logging for error conditions",
185 Self::Warn => "Enables logging for warning conditions",
186 Self::Notice => "Enables logging for normal but significant condition",
187 Self::Verbose => "Enables logging for verbose informational",
188 Self::Debug => "Enables logging for debug-level messages",
189 Self::Trace => "Enables logging for trace debug-level messages",
190 Self::Extra => "Enables logging for extra debug-level messages",
191 }
192 }
193}
194
195impl FromStr for LogLevel {
196 type Err = String;
197
198 fn from_str(s: &str) -> Result<Self, Self::Err> {
199 match s.to_lowercase().as_str() {
200 "fatal" => Ok(Self::Fatal),
201 "error" => Ok(Self::Error),
202 "warn" => Ok(Self::Warn),
203 "notice" => Ok(Self::Notice),
204 "verbose" => Ok(Self::Verbose),
205 "debug" => Ok(Self::Debug),
206 "trace" => Ok(Self::Trace),
207 "extra" => Ok(Self::Extra),
208 _ => Err(format!("Invalid log level: {s}")),
209 }
210 }
211}