#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EnvironmentFailureReason {
EnvLocked,
EnvNotFound,
LogChecksum,
LogFileNotFound,
LogRead,
LogWrite,
LogIntegrity,
LogIncomplete,
BtreeCorruption,
JavaError,
LatchAlreadyHeld,
LatchNotHeld,
ThreadInterrupted,
UncaughtException,
UnexpectedState,
UnexpectedStateFatal,
UnexpectedException,
UnexpectedExceptionFatal,
TestInvalidate,
HardRecovery,
ShutdownRequested,
Wedged,
}
impl EnvironmentFailureReason {
pub fn invalidates_environment(&self) -> bool {
!matches!(
self,
EnvironmentFailureReason::EnvLocked
| EnvironmentFailureReason::EnvNotFound
| EnvironmentFailureReason::LatchAlreadyHeld
| EnvironmentFailureReason::LatchNotHeld
| EnvironmentFailureReason::LogIntegrity
| EnvironmentFailureReason::UnexpectedState
| EnvironmentFailureReason::UnexpectedException
)
}
}
impl std::fmt::Display for EnvironmentFailureReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let msg = match self {
EnvironmentFailureReason::EnvLocked => {
"environment locked by another process"
}
EnvironmentFailureReason::EnvNotFound => {
"environment directory not found"
}
EnvironmentFailureReason::LogChecksum => "log file checksum error",
EnvironmentFailureReason::LogFileNotFound => "log file not found",
EnvironmentFailureReason::LogRead => "error reading log file",
EnvironmentFailureReason::LogWrite => "error writing log file",
EnvironmentFailureReason::LogIntegrity => "log integrity violation",
EnvironmentFailureReason::LogIncomplete => "incomplete log entry",
EnvironmentFailureReason::BtreeCorruption => {
"B-tree structure corruption"
}
EnvironmentFailureReason::JavaError => "Java-specific error",
EnvironmentFailureReason::LatchAlreadyHeld => {
"latch already held by current thread"
}
EnvironmentFailureReason::LatchNotHeld => {
"latch not held when expected"
}
EnvironmentFailureReason::ThreadInterrupted => {
"thread was interrupted"
}
EnvironmentFailureReason::UncaughtException => {
"uncaught exception occurred"
}
EnvironmentFailureReason::UnexpectedState => {
"unexpected state (non-fatal)"
}
EnvironmentFailureReason::UnexpectedStateFatal => {
"unexpected state (fatal)"
}
EnvironmentFailureReason::UnexpectedException => {
"unexpected exception (non-fatal)"
}
EnvironmentFailureReason::UnexpectedExceptionFatal => {
"unexpected exception (fatal)"
}
EnvironmentFailureReason::TestInvalidate => {
"test-induced invalidation"
}
EnvironmentFailureReason::HardRecovery => "hard recovery required",
EnvironmentFailureReason::ShutdownRequested => {
"shutdown was requested"
}
EnvironmentFailureReason::Wedged => {
"environment is wedged (unrecoverable)"
}
};
write!(f, "{}", msg)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_invalidates_environment() {
assert!(!EnvironmentFailureReason::EnvLocked.invalidates_environment());
assert!(
!EnvironmentFailureReason::EnvNotFound.invalidates_environment()
);
assert!(
!EnvironmentFailureReason::LatchAlreadyHeld
.invalidates_environment()
);
assert!(
!EnvironmentFailureReason::LatchNotHeld.invalidates_environment()
);
assert!(
!EnvironmentFailureReason::LogIntegrity.invalidates_environment()
);
assert!(
!EnvironmentFailureReason::UnexpectedState
.invalidates_environment()
);
assert!(
!EnvironmentFailureReason::UnexpectedException
.invalidates_environment()
);
assert!(
EnvironmentFailureReason::LogChecksum.invalidates_environment()
);
assert!(EnvironmentFailureReason::LogWrite.invalidates_environment());
assert!(
EnvironmentFailureReason::BtreeCorruption.invalidates_environment()
);
assert!(
EnvironmentFailureReason::UnexpectedStateFatal
.invalidates_environment()
);
assert!(EnvironmentFailureReason::Wedged.invalidates_environment());
}
#[test]
fn test_display() {
assert_eq!(
EnvironmentFailureReason::EnvLocked.to_string(),
"environment locked by another process"
);
assert_eq!(
EnvironmentFailureReason::LogChecksum.to_string(),
"log file checksum error"
);
assert_eq!(
EnvironmentFailureReason::BtreeCorruption.to_string(),
"B-tree structure corruption"
);
}
#[test]
fn test_all_variants_display() {
let reasons = vec![
EnvironmentFailureReason::EnvLocked,
EnvironmentFailureReason::EnvNotFound,
EnvironmentFailureReason::LogChecksum,
EnvironmentFailureReason::LogFileNotFound,
EnvironmentFailureReason::LogRead,
EnvironmentFailureReason::LogWrite,
EnvironmentFailureReason::LogIntegrity,
EnvironmentFailureReason::LogIncomplete,
EnvironmentFailureReason::BtreeCorruption,
EnvironmentFailureReason::JavaError,
EnvironmentFailureReason::LatchAlreadyHeld,
EnvironmentFailureReason::LatchNotHeld,
EnvironmentFailureReason::ThreadInterrupted,
EnvironmentFailureReason::UncaughtException,
EnvironmentFailureReason::UnexpectedState,
EnvironmentFailureReason::UnexpectedStateFatal,
EnvironmentFailureReason::UnexpectedException,
EnvironmentFailureReason::UnexpectedExceptionFatal,
EnvironmentFailureReason::TestInvalidate,
EnvironmentFailureReason::HardRecovery,
EnvironmentFailureReason::ShutdownRequested,
EnvironmentFailureReason::Wedged,
];
for reason in &reasons {
let display = reason.to_string();
assert!(!display.is_empty());
}
}
#[test]
fn test_equality() {
assert_eq!(
EnvironmentFailureReason::LogChecksum,
EnvironmentFailureReason::LogChecksum
);
assert_ne!(
EnvironmentFailureReason::LogChecksum,
EnvironmentFailureReason::LogWrite
);
}
}