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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
//! Provides [`FdbError`] type, [`FdbResult`] type alias and error
//! constants.
use std::convert::TryInto;
use std::error::Error;
use std::fmt::{self, Display};
use crate::option::ErrorPredicate;
/// Error type for this crate.
///
/// Internally it wraps FDB [Error Codes]. Error codes from 100 thru'
/// 999 is generated by the binding layer and not the C API.
///
/// [Error Codes]: https://apple.github.io/foundationdb/api-error-codes.html
//
// NOTE: 0 cannot be used for `error_code`.
//
// 100 - `database` module
// 110 - `tuple` module
// 120 - `subspace` module
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct FdbError {
/// FoundationDB error code `fdb_error_t`
error_code: i32,
}
/// Error occurred while opening database.
pub const DATABASE_OPEN: i32 = 100;
/// Error occurred while getting a value from the tuple.
pub const TUPLE_GET: i32 = 110;
/// Error occurred extracting a [`Tuple`] value from [`Bytes`].
///
/// [`Tuple`]: crate::tuple::Tuple
/// [`Bytes`]: bytes::Bytes
pub const TUPLE_TRY_FROM_BYTES: i32 = 111;
/// Error occurred extracting a [`Tuple`] value from [`Key`].
///
/// [`Tuple`]: crate::tuple::Tuple
/// [`Key`]: crate::Key
pub const TUPLE_TRY_FROM_KEY: i32 = 112;
/// Error occurred extracting a [`Tuple`] value from [`Value`].
///
/// [`Tuple`]: crate::tuple::Tuple
/// [`Value`]: crate::Value
pub const TUPLE_TRY_FROM_VALUE: i32 = 113;
/// Error occured when trying to pack [`Tuple`] containing an
/// incomplete [`Versionstamp`]. No incomplete [`Versionstamp`] found.
///
/// [`Tuple`]: crate::tuple::Tuple
/// [`Versionstamp`]: crate::tuple::Versionstamp
pub const TUPLE_PACK_WITH_VERSIONSTAMP_NOT_FOUND: i32 = 114;
/// Error occured when trying to pack [`Tuple`] containing an
/// incomplete [`Versionstamp`]. Multiple incomplete [`Versionstamp`]
/// found.
///
/// [`Tuple`]: crate::tuple::Tuple
/// [`Versionstamp`]: crate::tuple::Versionstamp
pub const TUPLE_PACK_WITH_VERSIONSTAMP_MULTIPLE_FOUND: i32 = 115;
/// Error occurred when calling [`strinc`], as the `prefix` supplied
/// is either empty or contains only `0xFF`.
///
/// [`strinc`]: crate::tuple::key_util::strinc
pub const TUPLE_KEY_UTIL_STRINC_ERROR: i32 = 116;
/// TODO
pub const TUPLE_VERSIONSTAMP_TRY_FROM: i32 = 117;
/// Error occured when trying to pack [`Subspace`] containing an
/// incomplete [`Versionstamp`]. Prefix contains an incomplete
/// [`Versionstamp`], which is not allowed.
///
/// [`Subspace`]: crate::subspace::Subspace
/// [`Versionstamp`]: crate::tuple::Versionstamp
pub const SUBSPACE_PACK_WITH_VERSIONSTAMP_PREFIX_INCOMPLETE: i32 = 120;
/// Error occured when trying to unpack a key. The provided key is not
/// contained in the [`Subspace`].
///
/// [`Subspace`]: crate::subspace::Subspace
pub const SUBSPACE_UNPACK_KEY_MISMATCH: i32 = 121;
/// Alias for [`Result`]`<T,`[`FdbError`]`>`
///
/// [`Result`]: std::result::Result
/// [`FdbError`]: crate::error::FdbError
pub type FdbResult<T> = Result<T, FdbError>;
impl FdbError {
/// Create new [`FdbError`]
pub fn new(err: i32) -> FdbError {
FdbError { error_code: err }
}
/// Returns raw FDB error code
pub fn code(self) -> i32 {
self.error_code
}
/// Returns `true` if the error indicates the operations in the
/// transactions should be retried because of transient error.
pub fn is_retryable(&self) -> bool {
unsafe {
// `FDB_ERROR_PREDICATE_RETRYABLE` has a value `50000`
// which can safely be converted into an `i32`.
//
// non-zero is `true`.
fdb_sys::fdb_error_predicate(
ErrorPredicate::Retryable.code().try_into().unwrap(),
self.error_code,
) != 0
}
}
/// Returns true if the error indicates the transaction may have
/// succeeded, though not in a way the system can verify.
pub fn is_maybe_committed(&self) -> bool {
unsafe {
// `FDB_ERROR_PREDICATE_MAYBE_COMMITTED` has a value
// `50001` which can safely be converted into an `i32`.
//
// non-zero is `true`.
fdb_sys::fdb_error_predicate(
ErrorPredicate::MaybeCommitted.code().try_into().unwrap(),
self.error_code,
) != 0
}
}
/// Returns `true` if the error indicates the transaction has not
/// committed, though in a way that can be retried.
pub fn is_retryable_not_committed(&self) -> bool {
unsafe {
// `FDB_ERROR_PREDICATE_RETRYABLE_NOT_COMMITTED` has a
// value `50002` which can safely be converted into an
// `i32`.
//
// non-zero is `true`.
fdb_sys::fdb_error_predicate(
ErrorPredicate::RetryableNotCommitted
.code()
.try_into()
.unwrap(),
self.error_code,
) != 0
}
}
/// Returns `true` if the error is from a layer. Returns `false`
/// if the error is a [C binding] error
///
/// [C binding]: https://apple.github.io/foundationdb/api-error-codes.html
pub(crate) fn layer_error(e: i32) -> bool {
(100..=999).contains(&e)
}
}
impl Error for FdbError {}
impl Display for FdbError {
fn fmt<'a>(&self, f: &mut fmt::Formatter<'a>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
/// Converts `fdb_error_t` to `FdbResult`
pub(crate) fn check(err: fdb_sys::fdb_error_t) -> FdbResult<()> {
if err == 0 {
Ok(())
} else {
Err(FdbError::new(err))
}
}