1use crate::directory::DirectoryError;
12use crate::options;
13use crate::tuple::hca::HcaError;
14use crate::tuple::PackError;
15use foundationdb_sys as fdb_sys;
16use std::ffi::CStr;
17use std::fmt;
18use std::fmt::{Debug, Display, Formatter};
19
20pub(crate) fn eval(error_code: fdb_sys::fdb_error_t) -> FdbResult<()> {
21 let rust_code: i32 = error_code;
22 if rust_code == 0 {
23 Ok(())
24 } else {
25 Err(FdbError::from_code(error_code))
26 }
27}
28
29#[derive(Debug)]
51pub struct TransactionMetricsNotFound;
52
53impl std::fmt::Display for TransactionMetricsNotFound {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "Transaction metrics not found")
56 }
57}
58
59impl std::error::Error for TransactionMetricsNotFound {}
60
61#[derive(Debug, Copy, Clone)]
63pub struct FdbError {
64 error_code: i32,
66}
67
68impl FdbError {
69 pub fn from_code(error_code: fdb_sys::fdb_error_t) -> Self {
71 Self { error_code }
72 }
73
74 #[cfg(feature = "tenant-experimental")]
75 pub(crate) fn new(error_code: i32) -> Self {
77 Self { error_code }
78 }
79
80 pub fn message(self) -> &'static str {
81 let error_str =
82 unsafe { CStr::from_ptr::<'static>(fdb_sys::fdb_get_error(self.error_code)) };
83 error_str
84 .to_str()
85 .expect("bad error string from FoundationDB")
86 }
87
88 fn is_error_predicate(self, predicate: options::ErrorPredicate) -> bool {
89 #[allow(clippy::unnecessary_cast)]
91 let check =
92 unsafe { fdb_sys::fdb_error_predicate(predicate.code() as i32, self.error_code) };
93
94 check != 0
95 }
96
97 pub fn is_maybe_committed(self) -> bool {
99 self.is_error_predicate(options::ErrorPredicate::MaybeCommitted)
100 }
101
102 pub fn is_retryable(self) -> bool {
104 self.is_error_predicate(options::ErrorPredicate::Retryable)
105 }
106
107 pub fn is_retryable_not_committed(self) -> bool {
109 self.is_error_predicate(options::ErrorPredicate::RetryableNotCommitted)
110 }
111
112 pub fn code(self) -> i32 {
114 self.error_code
115 }
116}
117
118impl fmt::Display for FdbError {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 std::fmt::Display::fmt(&self.message(), f)
121 }
122}
123
124impl std::error::Error for FdbError {}
125
126pub type FdbResult<T = ()> = Result<T, FdbError>;
128
129pub enum FdbBindingError {
132 NonRetryableFdbError(FdbError),
133 HcaError(HcaError),
134 DirectoryError(DirectoryError),
135 PackError(PackError),
136 ReferenceToTransactionKept,
138 CustomError(Box<dyn std::error::Error + Send + Sync>),
140 TransactionMetricsNotFound,
142}
143
144impl FdbBindingError {
145 pub fn get_fdb_error(&self) -> Option<FdbError> {
147 match *self {
148 Self::NonRetryableFdbError(error)
149 | Self::DirectoryError(DirectoryError::FdbError(error))
150 | Self::HcaError(HcaError::FdbError(error)) => Some(error),
151 Self::CustomError(ref error) => {
152 if let Some(e) = error.downcast_ref::<FdbError>() {
153 Some(*e)
154 } else if let Some(e) = error.downcast_ref::<FdbBindingError>() {
155 e.get_fdb_error()
156 } else {
157 None
158 }
159 }
160 _ => None,
161 }
162 }
163}
164
165impl From<FdbError> for FdbBindingError {
166 fn from(e: FdbError) -> Self {
167 Self::NonRetryableFdbError(e)
168 }
169}
170
171impl From<HcaError> for FdbBindingError {
172 fn from(e: HcaError) -> Self {
173 Self::HcaError(e)
174 }
175}
176
177impl From<DirectoryError> for FdbBindingError {
178 fn from(e: DirectoryError) -> Self {
179 Self::DirectoryError(e)
180 }
181}
182
183impl From<TransactionMetricsNotFound> for FdbBindingError {
184 fn from(_e: TransactionMetricsNotFound) -> Self {
185 Self::TransactionMetricsNotFound
186 }
187}
188
189impl FdbBindingError {
190 pub fn new_custom_error(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
192 Self::CustomError(e)
193 }
194}
195
196impl Debug for FdbBindingError {
197 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
198 match self {
199 FdbBindingError::NonRetryableFdbError(err) => write!(f, "{err:?}"),
200 FdbBindingError::HcaError(err) => write!(f, "{err:?}"),
201 FdbBindingError::DirectoryError(err) => write!(f, "{err:?}"),
202 FdbBindingError::PackError(err) => write!(f, "{err:?}"),
203 FdbBindingError::ReferenceToTransactionKept => {
204 write!(f, "Reference to transaction kept")
205 }
206 FdbBindingError::CustomError(err) => write!(f, "{err:?}"),
207 FdbBindingError::TransactionMetricsNotFound => {
208 write!(f, "Transaction metrics not found")
209 }
210 }
211 }
212}
213
214impl Display for FdbBindingError {
215 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
216 std::fmt::Debug::fmt(&self, f)
217 }
218}
219
220impl std::error::Error for FdbBindingError {}