pub mod heartbeat;
pub mod manager;
pub mod protocol;
pub mod replication;
pub mod role;
pub mod sync_handler;
pub mod sync_receiver;
use core::fmt;
#[cfg(feature = "log")]
use crate::log::debug;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum HARole {
Master,
Slave,
Auto,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ReplicationMode {
Sync,
Async,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SyncState {
Idle = 0,
Syncing = 1,
Synced = 2,
Failed = 3,
}
impl From<u32> for SyncState {
fn from(value: u32) -> Self {
match value {
0 => SyncState::Idle,
1 => SyncState::Syncing,
2 => SyncState::Synced,
3 => SyncState::Failed,
_ => SyncState::Idle,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct HAConfig {
pub node_id: u32,
pub ha_role: HARole,
pub replication_mode: ReplicationMode,
pub heartbeat_interval_ms: u64,
pub failure_detection_ms: u64,
pub sync_timeout_ms: u64,
pub master_address: Option<&'static str>,
pub master_port: Option<u16>,
pub replication_port: u16,
}
impl Default for HAConfig {
fn default() -> Self {
HAConfig {
node_id: 1,
ha_role: HARole::Auto,
replication_mode: ReplicationMode::Async,
heartbeat_interval_ms: 1000,
failure_detection_ms: 3000,
sync_timeout_ms: 2000,
master_address: None,
master_port: None,
replication_port: 5556,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum HAError {
InitFailed,
NetworkError,
InvalidParameter,
RoleConflict,
SyncFailed,
HeartbeatTimeout,
ReplicationError,
UnsupportedOperation,
}
impl fmt::Display for HAError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HAError::InitFailed => write!(f, "HA initialization failed"),
HAError::NetworkError => write!(f, "Network error"),
HAError::InvalidParameter => write!(f, "Invalid parameter"),
HAError::RoleConflict => write!(f, "Role conflict"),
HAError::SyncFailed => write!(f, "Sync failed"),
HAError::HeartbeatTimeout => write!(f, "Heartbeat timeout"),
HAError::ReplicationError => write!(f, "Replication error"),
HAError::UnsupportedOperation => write!(f, "Unsupported operation"),
}
}
}
pub type Result<T> = core::result::Result<T, HAError>;
static mut HA_MANAGER: Option<manager::HAManager> = None;
pub fn init(config: &'static crate::config::DbConfig) -> Result<()> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of_mut!(HA_MANAGER);
if (*ha_manager_ptr).is_some() {
return Err(HAError::InitFailed);
}
if config.ha_config.is_none() {
return Ok(());
}
#[cfg(feature = "log")]
debug!("ha::init: Creating HAManager instance");
let mut ha_manager = manager::HAManager::new(config)?;
#[cfg(feature = "log")]
debug!("ha::init: Calling ha_manager.init()");
ha_manager.init()?;
#[cfg(feature = "log")]
debug!("ha::init: Storing HAManager to global static");
*ha_manager_ptr = Some(ha_manager);
#[cfg(feature = "log")]
debug!("ha::init: HA initialization completed");
Ok(())
}
}
pub fn get_ha_manager() -> Option<&'static mut manager::HAManager> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of_mut!(HA_MANAGER);
(*ha_manager_ptr).as_mut()
}
}
pub fn shutdown() -> Result<()> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of_mut!(HA_MANAGER);
if let Some(ref mut manager) = *ha_manager_ptr {
let _ = manager.shutdown();
*ha_manager_ptr = None;
}
Ok(())
}
}
pub fn get_role() -> Result<HARole> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of!(HA_MANAGER);
if let Some(manager) = &*ha_manager_ptr {
Ok(manager.get_role())
} else {
Err(HAError::InitFailed)
}
}
}
pub fn get_replication_mode() -> Result<ReplicationMode> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of!(HA_MANAGER);
if let Some(manager) = &*ha_manager_ptr {
Ok(manager.get_replication_mode())
} else {
Err(HAError::InitFailed)
}
}
}
pub fn promote_to_master() -> Result<()> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of_mut!(HA_MANAGER);
if let Some(manager) = (*ha_manager_ptr).as_mut() {
manager.promote_to_master()
} else {
Err(HAError::InitFailed)
}
}
}
pub fn demote_to_slave() -> Result<()> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of_mut!(HA_MANAGER);
if let Some(manager) = (*ha_manager_ptr).as_mut() {
manager.demote_to_slave()
} else {
Err(HAError::InitFailed)
}
}
}
pub fn check_status() -> Result<()> {
unsafe {
let ha_manager_ptr = core::ptr::addr_of!(HA_MANAGER);
if let Some(manager) = &*ha_manager_ptr {
manager.check_status()
} else {
Err(HAError::InitFailed)
}
}
}