1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
910//! Persistence related errors.
1112use std::sync::Arc;
13use std::{error, fmt, io, sync};
1415use crate::location::{ExternalError, SeqNo};
1617/// A persistence related error.
18#[derive(Debug, Clone)]
19pub enum Error {
20/// A persistence related error resulting from an io failure.
21IO(Arc<io::Error>),
22/// An operation failed because storage was out of space or quota.
23OutOfQuota(String),
24/// An unstructured persistence related error.
25String(String),
26/// There is no stream registered under the given name.
27UnknownRegistration(String),
28/// The associated write request was sequenced (given a SeqNo) and applied
29 /// to the persist state machine, but that application was deterministically
30 /// made into a no-op because it was contextually invalid (a write or seal
31 /// at a sealed timestamp, an allow_compactions at an unsealed timestamp,
32 /// etc).
33Noop(SeqNo, String),
34/// An error returned when a command is sent to a persistence runtime that
35 /// was previously stopped.
36RuntimeShutdown,
37}
3839impl error::Error for Error {}
4041impl fmt::Display for Error {
42fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43match self {
44 Error::IO(e) => fmt::Display::fmt(e, f),
45 Error::OutOfQuota(e) => f.write_str(e),
46 Error::String(e) => f.write_str(e),
47 Error::UnknownRegistration(id) => write!(f, "unknown registration: {}", id),
48 Error::Noop(_, e) => f.write_str(e),
49 Error::RuntimeShutdown => f.write_str("runtime shutdown"),
50 }
51 }
52}
5354// Hack so we can debug_assert_eq against Result<(), Error>.
55impl PartialEq for Error {
56fn eq(&self, other: &Self) -> bool {
57match (self, other) {
58 (Error::String(s), Error::String(o)) => s == o,
59 (Error::OutOfQuota(s), Error::OutOfQuota(o)) => s == o,
60 (Error::UnknownRegistration(s), Error::UnknownRegistration(o)) => s == o,
61 (Error::RuntimeShutdown, Error::RuntimeShutdown) => true,
62_ => false,
63 }
64 }
65}
6667impl From<ExternalError> for Error {
68fn from(e: ExternalError) -> Self {
69// Print the chain of causes along with each error by default.
70Error::String(format!("{e:#}"))
71 }
72}
7374impl From<io::Error> for Error {
75fn from(e: io::Error) -> Self {
76// This only works on unix/macos, but I don't see a great alternative.
77if let Some(28) = e.raw_os_error() {
78return Error::OutOfQuota(e.to_string());
79 }
80 Error::IO(Arc::new(e))
81 }
82}
8384impl From<String> for Error {
85fn from(e: String) -> Self {
86 Error::String(e)
87 }
88}
8990impl<'a> From<&'a str> for Error {
91fn from(e: &'a str) -> Self {
92 Error::String(e.into())
93 }
94}
9596impl From<parquet::errors::ParquetError> for Error {
97fn from(e: parquet::errors::ParquetError) -> Self {
98 Error::String(e.to_string())
99 }
100}
101102impl From<arrow::error::ArrowError> for Error {
103fn from(e: arrow::error::ArrowError) -> Self {
104 Error::String(e.to_string())
105 }
106}
107108impl<T> From<sync::PoisonError<T>> for Error {
109fn from(e: sync::PoisonError<T>) -> Self {
110 Error::String(format!("poison: {}", e))
111 }
112}