1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//! Error types for the DBI layer.
//!
use thiserror::Error;
/// Errors that can occur in the DBI layer.
#[derive(Debug, Error)]
pub enum DbiError {
/// Database not found.
#[error("database not found: {0}")]
DatabaseNotFound(String),
/// Database already exists.
#[error("database already exists: {0}")]
DatabaseAlreadyExists(String),
/// Database already exists (compatibility alias).
#[error("database already exists: {0}")]
DatabaseExists(String),
/// Database cannot be deleted or renamed while handles are open.
///
/// Thrown when
/// `EnvironmentImpl.dbRemove()`/`dbRename()` detect open handles.
#[error("database is in use (open handles exist): {0}")]
DatabaseInUse(String),
/// Environment failure.
#[error("environment failure: {reason}")]
EnvironmentFailure { reason: String },
/// Recovery failed during environment open.
///
/// Distinct from the more general `EnvironmentFailure` so callers
/// can branch on "recovery couldn't replay the WAL" specifically.
/// Wave 1C audit cleanup (transaction-env F22 typed recovery-
/// failure variant): previously every recovery failure surfaced
/// as `EnvironmentFailure { reason: "recovery failed: ..." }`,
/// which forced callers to string-match the prefix.
#[error("recovery failed: {reason}")]
RecoveryFailure { reason: String },
/// Environment is not open.
#[error("environment not open")]
EnvironmentNotOpen,
/// Environment is locked by another process.
#[error("environment locked: {0}")]
EnvironmentLocked(String),
/// Cursor not initialized.
#[error("cursor not initialized")]
CursorNotInitialized,
/// Cursor is closed.
#[error("cursor closed")]
CursorClosed,
/// Operation failed.
#[error("operation status: {0}")]
OperationFailed(String),
/// Lock conflict occurred.
#[error("lock conflict: {0}")]
LockConflict(String),
/// Transaction error.
#[error("transaction error: {0}")]
TxnError(#[from] noxu_txn::TxnError),
/// Tree error.
#[error("tree error: {0}")]
TreeError(#[from] noxu_tree::TreeError),
/// I/O error.
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
/// Log subsystem error.
#[error("log error: {0}")]
LogError(#[from] noxu_log::NoxuLogError),
}
/// Result type for DBI operations.
pub type Result<T> = std::result::Result<T, DbiError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = DbiError::DatabaseNotFound("test_db".to_string());
assert_eq!(err.to_string(), "database not found: test_db");
let err = DbiError::EnvironmentNotOpen;
assert_eq!(err.to_string(), "environment not open");
}
#[test]
fn test_error_from_io() {
let io_err =
std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let dbi_err: DbiError = io_err.into();
assert!(matches!(dbi_err, DbiError::IoError(_)));
}
}