1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::fmt::{Debug, Display};
use std::io::{Error as IoError, ErrorKind};
use std::{error, result};
use error_code::{self, ErrorCode, ErrorCodeExt};
use openssl::error::ErrorStack as CrypterError;
use protobuf::ProtobufError;
use thiserror::Error;
use tikv_util::stream::RetryError;
pub trait RetryCodedError: Debug + Display + ErrorCodeExt + RetryError + Send + Sync {}
#[derive(Debug, Error)]
pub enum Error {
#[error("Other error {0}")]
Other(#[from] Box<dyn error::Error + Sync + Send>),
#[error("Recoverable tail record corruption while parsing file dictionary")]
TailRecordParseIncomplete,
#[error("Cloud KMS error {0}")]
RetryCodedError(Box<dyn RetryCodedError>),
#[error("RocksDB error {0}")]
Rocks(String),
#[error("IO error {0}")]
Io(#[from] IoError),
#[error("OpenSSL error {0}")]
Crypter(#[from] CrypterError),
#[error("Protobuf error {0}")]
Proto(#[from] ProtobufError),
#[error("Unknown encryption error")]
UnknownEncryption,
#[error("Wrong master key error {0}")]
WrongMasterKey(Box<dyn error::Error + Sync + Send>),
#[error("Both master key failed, current key {0}, previous key {1}.")]
BothMasterKeyFail(
Box<dyn error::Error + Sync + Send>,
Box<dyn error::Error + Sync + Send>,
),
}
macro_rules! impl_from {
($($inner:ty => $container:ident,)+) => {
$(
impl From<$inner> for Error {
fn from(inr: $inner) -> Error {
Error::$container(inr)
}
}
)+
};
}
impl_from! {
String => Rocks,
}
impl From<Error> for IoError {
fn from(err: Error) -> IoError {
match err {
Error::Io(e) => e,
other => IoError::new(ErrorKind::Other, format!("{}", other)),
}
}
}
pub type Result<T> = result::Result<T, Error>;
impl ErrorCodeExt for Error {
fn error_code(&self) -> ErrorCode {
match self {
Error::RetryCodedError(err) => err.error_code(),
Error::TailRecordParseIncomplete => error_code::encryption::PARSE_INCOMPLETE,
Error::Rocks(_) => error_code::encryption::ROCKS,
Error::Io(_) => error_code::encryption::IO,
Error::Crypter(_) => error_code::encryption::CRYPTER,
Error::Proto(_) => error_code::encryption::PROTO,
Error::UnknownEncryption => error_code::encryption::UNKNOWN_ENCRYPTION,
Error::WrongMasterKey(_) => error_code::encryption::WRONG_MASTER_KEY,
Error::BothMasterKeyFail(..) => error_code::encryption::BOTH_MASTER_KEY_FAIL,
Error::Other(_) => error_code::UNKNOWN,
}
}
}
impl RetryError for Error {
fn is_retryable(&self) -> bool {
match self {
Error::RetryCodedError(err) => err.is_retryable(),
Error::TailRecordParseIncomplete => true,
Error::Rocks(_) => true,
Error::Io(_) => true,
Error::Crypter(_) => true,
Error::Proto(_) => true,
Error::UnknownEncryption => true,
Error::WrongMasterKey(_) => false,
Error::BothMasterKeyFail(..) => false,
Error::Other(_) => true,
}
}
}