Improve error reporting infrastructure
This commit greatly improves the error reporting infrastructure all across the `skyd` crate. Now, every error has far more context making it easier to debug and test while also providing helpful feedback to users. This feedback can be extremely helpful to find out offending files and fix them; for example, by being specific about which file is corrupted or has bad metadata.next
parent
624c7e5aaa
commit
d57b0d98cf
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Created on Sat Mar 26 2022
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2022, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::corestore::memstore::ObjectID;
|
||||
use core::fmt;
|
||||
use std::io::Error as IoError;
|
||||
|
||||
pub type StorageEngineResult<T> = Result<T, StorageEngineError>;
|
||||
|
||||
pub trait ErrorContext<T> {
|
||||
/// Provide some context to an error
|
||||
fn map_err_context(self, extra: impl ToString) -> StorageEngineResult<T>;
|
||||
}
|
||||
|
||||
impl<T> ErrorContext<T> for Result<T, IoError> {
|
||||
fn map_err_context(self, extra: impl ToString) -> StorageEngineResult<T> {
|
||||
self.map_err(|e| StorageEngineError::ioerror_extra(e, extra.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StorageEngineError {
|
||||
/// An I/O Error
|
||||
IoError(IoError),
|
||||
/// An I/O Error with extra context
|
||||
IoErrorExtra(IoError, String),
|
||||
/// A corrupted file
|
||||
CorruptedFile(String),
|
||||
/// The file contains bad metadata
|
||||
BadMetadata(String),
|
||||
}
|
||||
|
||||
impl StorageEngineError {
|
||||
pub fn corrupted_partmap(ksid: &ObjectID) -> Self {
|
||||
Self::CorruptedFile(format!("{ksid}/PARTMAP", ksid = unsafe { ksid.as_str() }))
|
||||
}
|
||||
pub fn bad_metadata_in_table(ksid: &ObjectID, table: &ObjectID) -> Self {
|
||||
unsafe {
|
||||
Self::CorruptedFile(format!(
|
||||
"{ksid}/{table}",
|
||||
ksid = ksid.as_str(),
|
||||
table = table.as_str()
|
||||
))
|
||||
}
|
||||
}
|
||||
pub fn corrupted_preload() -> Self {
|
||||
Self::CorruptedFile("PRELOAD".into())
|
||||
}
|
||||
pub fn ioerror_extra(ioe: IoError, extra: impl ToString) -> Self {
|
||||
Self::IoErrorExtra(ioe, extra.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IoError> for StorageEngineError {
|
||||
fn from(ioe: IoError) -> Self {
|
||||
Self::IoError(ioe)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StorageEngineError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::IoError(ioe) => write!(f, "I/O error: {}", ioe),
|
||||
Self::IoErrorExtra(ioe, extra) => write!(f, "I/O error while {extra}: {ioe}"),
|
||||
Self::CorruptedFile(cfile) => write!(f, "file `{cfile}` is corrupted"),
|
||||
Self::BadMetadata(file) => write!(f, "bad metadata in file `{file}`"),
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Created on Sat Mar 26 2022
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2022, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::storage::v1::{error::StorageEngineError, sengine::SnapshotEngineError};
|
||||
use openssl::{error::ErrorStack as SslErrorStack, ssl::Error as SslError};
|
||||
use std::{fmt, io::Error as IoError};
|
||||
|
||||
pub type SkyResult<T> = Result<T, Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Storage(StorageEngineError),
|
||||
IoError(IoError),
|
||||
IoErrorExtra(IoError, String),
|
||||
OtherError(String),
|
||||
TlsError(SslError),
|
||||
SnapshotEngineError(SnapshotEngineError),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn ioerror_extra(ioe: IoError, extra: impl ToString) -> Self {
|
||||
Self::IoErrorExtra(ioe, extra.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Storage(serr) => write!(f, "Storage engine error: {}", serr),
|
||||
Self::IoError(nerr) => write!(f, "I/O error: {}", nerr),
|
||||
Self::IoErrorExtra(ioe, extra) => write!(f, "I/O error while {extra}: {ioe}"),
|
||||
Self::OtherError(oerr) => write!(f, "Error: {}", oerr),
|
||||
Self::TlsError(terr) => write!(f, "TLS error: {}", terr),
|
||||
Self::SnapshotEngineError(snaperr) => write!(f, "Snapshot engine error: {snaperr}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
fn from(ioe: IoError) -> Self {
|
||||
Self::IoError(ioe)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StorageEngineError> for Error {
|
||||
fn from(see: StorageEngineError) -> Self {
|
||||
Self::Storage(see)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SslError> for Error {
|
||||
fn from(sslerr: SslError) -> Self {
|
||||
Self::TlsError(sslerr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SslErrorStack> for Error {
|
||||
fn from(estack: SslErrorStack) -> Self {
|
||||
Self::TlsError(estack.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SnapshotEngineError> for Error {
|
||||
fn from(snaperr: SnapshotEngineError) -> Self {
|
||||
Self::SnapshotEngineError(snaperr)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue