use crate::internal_prelude::*;
#[derive(Debug, Clone, Error)]
#[non_exhaustive]
pub enum Error {
#[error("attempted to use shut down memory tracker")]
TrackerShutdown,
#[error("memquota - attempted to use closed memory tracking account")]
AccountClosed,
#[error("memquota - attempted to insert a duplicate child account")]
ChildAccountAlreadyExists,
#[error("memquota - attempt to allocate by torn-down memory tracking participant")]
ParticipantShutdown,
#[error("{TrackerCorrupted}")]
TrackerCorrupted,
#[error("internal error")]
Bug(#[from] Bug),
}
#[derive(Debug, Clone, Error, Default)]
#[non_exhaustive]
#[error("{0}")]
pub struct MemoryReclaimedError(ReclaimedErrorInner);
#[derive(Debug, Clone, Error, Default)]
enum ReclaimedErrorInner {
#[error("data structure discarded due to memory pressure")]
#[default]
Collapsed,
#[error("{0}")]
TrackerError(#[from] Error),
}
#[derive(Debug, Clone, Error)]
#[non_exhaustive]
pub enum StartupError {
#[error("couldn't spawn reclamation task")]
Spawn(#[source] Arc<SpawnError>),
}
impl From<SpawnError> for StartupError {
fn from(e: SpawnError) -> StartupError {
StartupError::Spawn(Arc::new(e))
}
}
#[derive(Debug, Clone, Error)]
#[error("memory tracker is corrupted due to previous bug")]
pub struct TrackerCorrupted;
impl<T> From<PoisonError<T>> for TrackerCorrupted {
fn from(_: PoisonError<T>) -> TrackerCorrupted {
TrackerCorrupted
}
}
impl From<TrackerCorrupted> for Error {
fn from(_: TrackerCorrupted) -> Error {
Error::TrackerCorrupted
}
}
#[derive(Debug, Clone, Error)]
pub(crate) enum ReclaimCrashed {
#[error("memory tracker corrupted due to previous bug")]
TrackerCorrupted(#[from] TrackerCorrupted),
#[error("internal error")]
Bug(#[from] Bug),
}
impl MemoryReclaimedError {
pub fn new() -> Self {
MemoryReclaimedError::default()
}
}
impl From<Error> for MemoryReclaimedError {
fn from(e: Error) -> MemoryReclaimedError {
MemoryReclaimedError(e.into())
}
}
impl HasKind for MemoryReclaimedError {
fn kind(&self) -> ErrorKind {
self.0.kind()
}
}
impl HasKind for ReclaimedErrorInner {
fn kind(&self) -> ErrorKind {
use ErrorKind as EK;
use ReclaimedErrorInner as REI;
match self {
REI::Collapsed => EK::LocalResourceExhausted,
REI::TrackerError(e) => e.kind(),
}
}
}
impl HasKind for Error {
fn kind(&self) -> ErrorKind {
use Error as E;
use ErrorKind as EK;
match self {
E::TrackerShutdown => EK::ArtiShuttingDown,
E::AccountClosed => EK::LocalResourceExhausted,
E::ChildAccountAlreadyExists => EK::BadApiUsage,
E::ParticipantShutdown => EK::LocalResourceExhausted,
E::TrackerCorrupted => EK::Internal,
E::Bug(e) => e.kind(),
}
}
}
impl HasKind for TrackerCorrupted {
fn kind(&self) -> ErrorKind {
use ErrorKind as EK;
match self {
TrackerCorrupted => EK::Internal,
}
}
}
impl HasKind for StartupError {
fn kind(&self) -> ErrorKind {
use StartupError as SE;
match self {
SE::Spawn(e) => e.kind(),
}
}
}
impl HasKind for ReclaimCrashed {
fn kind(&self) -> ErrorKind {
use ReclaimCrashed as RC;
match self {
RC::TrackerCorrupted(e) => e.kind(),
RC::Bug(e) => e.kind(),
}
}
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_time_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
#![allow(clippy::string_slice)] use super::*;
use fmt::Display;
#[test]
fn error_display() {
fn check_value(e: impl Debug + Display + HasKind) {
println!("{e:?} / {e} / {:?}", e.kind());
}
let bug = internal!("error made for testingr");
macro_rules! check_enum { {
$ty:ident: $( $variant:ident $fields:tt; )*
} => {
for e in [ $(
$ty::$variant $fields,
)* ] {
check_value(e);
}
match None::<$ty> {
None => {}
$( Some($ty::$variant { .. }) => {}, )*
}
} }
check_enum! {
Error:
TrackerShutdown {};
AccountClosed {};
ChildAccountAlreadyExists {};
ParticipantShutdown {};
TrackerCorrupted {};
Bug(bug.clone());
}
check_enum! {
ReclaimedErrorInner:
Collapsed {};
TrackerError(Error::TrackerShutdown);
}
check_value(MemoryReclaimedError(ReclaimedErrorInner::Collapsed));
check_enum! {
StartupError:
Spawn(SpawnError::shutdown().into());
}
check_value(TrackerCorrupted);
check_enum! {
ReclaimCrashed:
TrackerCorrupted(TrackerCorrupted);
Bug(bug.clone());
}
}
}