hypercall/snapshot/
sync.rs1use std::sync::atomic::{AtomicU8, Ordering};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[repr(u8)]
10pub enum SyncState {
11 Initializing = 0,
13 CatchingUp = 1,
15 Ready = 2,
17}
18
19impl std::fmt::Display for SyncState {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 SyncState::Initializing => write!(f, "Initializing"),
23 SyncState::CatchingUp => write!(f, "CatchingUp"),
24 SyncState::Ready => write!(f, "Ready"),
25 }
26 }
27}
28
29pub struct SyncStatus {
34 state: AtomicU8,
35}
36
37impl SyncStatus {
38 pub fn new() -> Self {
40 Self {
41 state: AtomicU8::new(SyncState::Initializing as u8),
42 }
43 }
44
45 pub fn state(&self) -> SyncState {
47 match self.state.load(Ordering::SeqCst) {
48 0 => SyncState::Initializing,
49 1 => SyncState::CatchingUp,
50 2 => SyncState::Ready,
51 _ => SyncState::Initializing,
52 }
53 }
54
55 pub fn is_ready(&self) -> bool {
57 self.state() == SyncState::Ready
58 }
59
60 pub fn set_catching_up(&self) {
62 self.state
63 .store(SyncState::CatchingUp as u8, Ordering::SeqCst);
64 }
65
66 pub fn set_ready(&self) {
68 self.state.store(SyncState::Ready as u8, Ordering::SeqCst);
69 }
70}
71
72impl Default for SyncStatus {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_sync_status_state_machine() {
84 let status = SyncStatus::new();
85 assert_eq!(status.state(), SyncState::Initializing);
86 assert!(!status.is_ready());
87
88 status.set_catching_up();
89 assert_eq!(status.state(), SyncState::CatchingUp);
90 assert!(!status.is_ready());
91
92 status.set_ready();
93 assert_eq!(status.state(), SyncState::Ready);
94 assert!(status.is_ready());
95 }
96
97 #[test]
98 fn test_sync_state_display() {
99 assert_eq!(format!("{}", SyncState::Initializing), "Initializing");
100 assert_eq!(format!("{}", SyncState::CatchingUp), "CatchingUp");
101 assert_eq!(format!("{}", SyncState::Ready), "Ready");
102 }
103}