use crate::utils::ffi;
use crate::data::error::RedundancyState;
#[derive(Clone, Debug)]
pub struct RedundancyInfo {
pub state: RedundancyState,
pub primary_link_up: bool,
pub secondary_link_up: bool,
pub primary_tx_frames: u32,
pub primary_rx_frames: u32,
pub secondary_tx_frames: u32,
pub secondary_rx_frames: u32,
pub failover_count: u32,
pub last_failover_time: u32,
}
impl std::fmt::Display for RedundancyInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let state_str = match self.state {
RedundancyState::None => "无冗余",
RedundancyState::Primary => "主网络",
RedundancyState::Secondary => "备用网络",
RedundancyState::Both => "双网络活动",
};
write!(
f,
"状态: {}, 主链路: {}, 备链路: {}, 故障转移: {} 次",
state_str,
if self.primary_link_up { "UP" } else { "DOWN" },
if self.secondary_link_up { "UP" } else { "DOWN" },
self.failover_count,
)
}
}
pub struct RedundancyManager {
master_index: u16,
}
impl RedundancyManager {
pub fn new(master_index: u16) -> Self {
Self { master_index }
}
pub fn enable(&self, enable: bool) -> bool {
unsafe { ffi::EnableRedundancy(self.master_index, if enable { 1 } else { 0 }) != 0 }
}
pub fn status(&self) -> Option<RedundancyInfo> {
unsafe {
let ptr = ffi::GetRedundancyStatus(self.master_index);
if ptr.is_null() {
return None;
}
let native = &*(ptr as *const ffi::RedundancyStatus);
let info = RedundancyInfo {
state: match native.state {
0 => RedundancyState::None,
1 => RedundancyState::Primary,
2 => RedundancyState::Secondary,
3 => RedundancyState::Both,
_ => RedundancyState::None,
},
primary_link_up: native.primary_link_up != 0,
secondary_link_up: native.secondary_link_up != 0,
primary_tx_frames: native.primary_tx_frames,
primary_rx_frames: native.primary_rx_frames,
secondary_tx_frames: native.secondary_tx_frames,
secondary_rx_frames: native.secondary_rx_frames,
failover_count: native.failover_count,
last_failover_time: native.last_failover_time,
};
ffi::FreeMemory(ptr as *mut std::os::raw::c_void);
Some(info)
}
}
pub fn force_failover(&self) -> bool {
unsafe { ffi::ForceRedundancyFailover(self.master_index) != 0 }
}
pub fn check_health(&self) -> bool {
unsafe { ffi::CheckRedundancyHealth(self.master_index) != 0 }
}
pub fn secondary_link_status(&self) -> bool {
unsafe { ffi::GetSecondaryLinkStatus(self.master_index) != 0 }
}
pub fn ring_mode(&self) -> i32 {
unsafe { ffi::GetRingMode(self.master_index) }
}
pub fn set_red_processdata(&self, mode: i32) {
unsafe { ffi::SetRedProcessdata(mode) }
}
pub fn get_red_processdata(&self) -> i32 {
unsafe { ffi::GetRedProcessdata() }
}
}