use std::sync::OnceLock;
pub mod index;
pub mod keypos;
pub mod message;
pub mod msg_type;
pub mod queue;
pub mod request;
pub mod response;
pub mod response_mgr;
pub use self::index::MsgIndex;
pub use self::keypos::{ArgPos, KeyPos};
pub use self::message::{ConnId, Msg, MsgFlags, MsgParseResult, MsgRouting};
pub use self::msg_type::MsgType;
pub use self::queue::MsgQueue;
pub use self::response_mgr::{QuorumOutcome, ResponseMgr, MAX_REPLICAS_PER_DC};
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
#[repr(u8)]
pub enum ConsistencyLevel {
#[default]
DcOne = 0,
DcQuorum = 1,
DcSafeQuorum = 2,
DcEachSafeQuorum = 3,
}
impl ConsistencyLevel {
#[must_use]
pub fn name(self) -> &'static str {
match self {
ConsistencyLevel::DcOne => "DC_ONE",
ConsistencyLevel::DcQuorum => "DC_QUORUM",
ConsistencyLevel::DcSafeQuorum => "DC_SAFE_QUORUM",
ConsistencyLevel::DcEachSafeQuorum => "DC_EACH_SAFE_QUORUM",
}
}
#[must_use]
pub fn from_name(name: &str) -> Option<Self> {
match name {
"DC_ONE" => Some(Self::DcOne),
"DC_QUORUM" => Some(Self::DcQuorum),
"DC_SAFE_QUORUM" => Some(Self::DcSafeQuorum),
"DC_EACH_SAFE_QUORUM" => Some(Self::DcEachSafeQuorum),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
#[repr(u8)]
pub enum DynErrorCode {
#[default]
Ok = 0,
DynomiteUnknownError = 1,
DynomiteInvalidState = 2,
DynomiteInvalidAdminReq = 3,
PeerConnectionRefuse = 4,
PeerHostDown = 5,
PeerHostNotConnected = 6,
StorageConnectionRefuse = 7,
BadFormat = 8,
DynomiteNoQuorumAchieved = 9,
DynomiteScriptSpansNodes = 10,
DynomitePayloadTooLarge = 11,
}
impl DynErrorCode {
#[must_use]
pub fn message(self) -> &'static str {
match self {
DynErrorCode::Ok => "Success",
DynErrorCode::DynomiteUnknownError => "Unknown Error",
DynErrorCode::DynomiteInvalidState => {
"Dynomite's current state does not allow this request"
}
DynErrorCode::DynomiteInvalidAdminReq => "Invalid request in Dynomite's admin mode",
DynErrorCode::PeerConnectionRefuse => "Peer Node refused connection",
DynErrorCode::PeerHostDown => "Peer Node is down",
DynErrorCode::PeerHostNotConnected => "Peer Node is not connected",
DynErrorCode::StorageConnectionRefuse => "Datastore refused connection",
DynErrorCode::BadFormat => "Bad message format",
DynErrorCode::DynomiteNoQuorumAchieved => "Failed to achieve Quorum",
DynErrorCode::DynomiteScriptSpansNodes => {
"Keys in the script cannot span multiple nodes"
}
DynErrorCode::DynomitePayloadTooLarge => "MSET/MGET/SCAN payload too large",
}
}
#[must_use]
pub fn source(self) -> &'static str {
match self {
DynErrorCode::DynomiteInvalidAdminReq
| DynErrorCode::DynomiteInvalidState
| DynErrorCode::DynomiteNoQuorumAchieved
| DynErrorCode::DynomiteScriptSpansNodes
| DynErrorCode::DynomitePayloadTooLarge => "Dynomite:",
DynErrorCode::PeerConnectionRefuse
| DynErrorCode::PeerHostDown
| DynErrorCode::PeerHostNotConnected => "Peer:",
DynErrorCode::StorageConnectionRefuse => "Storage:",
_ => "unknown:",
}
}
}
static READ_REPAIRS_ENABLED: OnceLock<bool> = OnceLock::new();
pub fn set_read_repairs_enabled(enabled: bool) -> bool {
READ_REPAIRS_ENABLED.set(enabled).is_ok()
}
#[must_use]
pub fn is_read_repairs_enabled() -> bool {
*READ_REPAIRS_ENABLED.get().unwrap_or(&false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn consistency_round_trip() {
for level in [
ConsistencyLevel::DcOne,
ConsistencyLevel::DcQuorum,
ConsistencyLevel::DcSafeQuorum,
ConsistencyLevel::DcEachSafeQuorum,
] {
assert_eq!(ConsistencyLevel::from_name(level.name()), Some(level));
}
assert!(ConsistencyLevel::from_name("DC_BOGUS").is_none());
}
#[test]
fn dyn_error_code_strings_match_c() {
assert_eq!(DynErrorCode::Ok.message(), "Success");
assert_eq!(DynErrorCode::PeerHostDown.source(), "Peer:");
assert_eq!(DynErrorCode::DynomiteUnknownError.source(), "unknown:");
assert_eq!(DynErrorCode::StorageConnectionRefuse.source(), "Storage:");
}
}