use std::fmt;
use crate::sync::ballot::Ballot;
use crate::tree::Hash;
use crate::wal::WalError;
use super::handle::ShardError;
#[derive(Debug)]
pub(super) enum AppendError {
SequenceConflict { expected: u64, actual: u64 },
Wal(WalError),
}
impl fmt::Display for AppendError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SequenceConflict { expected, actual } => write!(
formatter,
"sequence conflict on append: expected {expected}, actual {actual}"
),
Self::Wal(error) => write!(formatter, "append WAL error: {error}"),
}
}
}
impl std::error::Error for AppendError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Wal(error) => Some(error),
Self::SequenceConflict { .. } => None,
}
}
}
impl From<WalError> for AppendError {
fn from(error: WalError) -> Self {
Self::Wal(error)
}
}
impl From<AppendError> for ShardError {
fn from(error: AppendError) -> Self {
match error {
AppendError::SequenceConflict { expected, actual } => {
Self::SequenceConflict { expected, actual }
}
AppendError::Wal(error) => Self::from(error),
}
}
}
#[derive(Debug)]
pub(super) enum CasError {
Mismatch {
expected: Option<u64>,
actual: Option<u64>,
},
Wal(WalError),
}
impl fmt::Display for CasError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Mismatch { expected, actual } => write!(
formatter,
"cas mismatch: expected {expected:?}, actual {actual:?}"
),
Self::Wal(error) => write!(formatter, "cas WAL error: {error}"),
}
}
}
impl std::error::Error for CasError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Wal(error) => Some(error),
Self::Mismatch { .. } => None,
}
}
}
impl From<WalError> for CasError {
fn from(error: WalError) -> Self {
Self::Wal(error)
}
}
impl From<CasError> for ShardError {
fn from(error: CasError) -> Self {
match error {
CasError::Mismatch { expected, actual } => Self::CasMismatch { expected, actual },
CasError::Wal(error) => Self::from(error),
}
}
}
#[derive(Debug)]
pub(super) enum HashCasError {
HashMismatch {
expected: Option<Hash>,
actual: Option<Hash>,
},
Fenced {
promised: Ballot,
attempted: Ballot,
},
Wal(WalError),
}
impl fmt::Display for HashCasError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::HashMismatch { expected, actual } => write!(
formatter,
"hash cas mismatch: expected {expected:?}, actual {actual:?}"
),
Self::Fenced {
promised,
attempted,
} => write!(
formatter,
"epoch fence: attempted {attempted:?} < promised {promised:?}"
),
Self::Wal(error) => write!(formatter, "apply WAL error: {error}"),
}
}
}
impl std::error::Error for HashCasError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Wal(error) => Some(error),
Self::HashMismatch { .. } | Self::Fenced { .. } => None,
}
}
}
impl From<WalError> for HashCasError {
fn from(error: WalError) -> Self {
Self::Wal(error)
}
}
impl From<HashCasError> for ShardError {
fn from(error: HashCasError) -> Self {
match error {
HashCasError::HashMismatch { expected, actual } => {
Self::CasHashMismatch { expected, actual }
}
HashCasError::Fenced {
promised,
attempted,
} => Self::Fenced {
promised,
attempted,
},
HashCasError::Wal(error) => Self::from(error),
}
}
}