dbx_core/replication/
vector_clock.rs1use std::collections::HashMap;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum VectorClockOrder {
18 HappensBefore,
20 HappensAfter,
22 Concurrent,
24 Equal,
26}
27
28#[derive(Debug, Clone, Default, PartialEq)]
32pub struct VectorClock {
33 clocks: HashMap<u32, u64>,
34}
35
36impl VectorClock {
37 pub fn new() -> Self {
39 Self {
40 clocks: HashMap::new(),
41 }
42 }
43
44 pub fn get(&self, node_id: u32) -> u64 {
46 *self.clocks.get(&node_id).unwrap_or(&0)
47 }
48
49 pub fn tick(&mut self, node_id: u32) {
51 let entry = self.clocks.entry(node_id).or_insert(0);
52 *entry += 1;
53 }
54
55 pub fn merge_and_tick(&mut self, other: &VectorClock, self_node_id: u32) {
57 for (&node_id, &clock) in &other.clocks {
58 let entry = self.clocks.entry(node_id).or_insert(0);
59 *entry = (*entry).max(clock);
60 }
61 self.tick(self_node_id);
62 }
63
64 pub fn merge(&mut self, other: &VectorClock) {
66 for (&node_id, &clock) in &other.clocks {
67 let entry = self.clocks.entry(node_id).or_insert(0);
68 *entry = (*entry).max(clock);
69 }
70 }
71
72 pub fn compare(&self, other: &VectorClock) -> VectorClockOrder {
74 let mut self_gt = false; let mut other_gt = false; let all_nodes: std::collections::HashSet<u32> = self
79 .clocks
80 .keys()
81 .chain(other.clocks.keys())
82 .copied()
83 .collect();
84
85 for node in all_nodes {
86 let lhs = self.get(node);
87 let rhs = other.get(node);
88 if lhs > rhs {
89 self_gt = true;
90 }
91 if rhs > lhs {
92 other_gt = true;
93 }
94 }
95
96 match (self_gt, other_gt) {
97 (false, false) => VectorClockOrder::Equal,
98 (true, false) => VectorClockOrder::HappensAfter,
99 (false, true) => VectorClockOrder::HappensBefore,
100 (true, true) => VectorClockOrder::Concurrent,
101 }
102 }
103
104 pub fn happens_before(&self, other: &VectorClock) -> bool {
106 self.compare(other) == VectorClockOrder::HappensBefore
107 }
108
109 pub fn is_concurrent(&self, other: &VectorClock) -> bool {
111 self.compare(other) == VectorClockOrder::Concurrent
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_tick_and_get() {
121 let mut vc = VectorClock::new();
122 vc.tick(1);
123 vc.tick(1);
124 vc.tick(2);
125 assert_eq!(vc.get(1), 2);
126 assert_eq!(vc.get(2), 1);
127 assert_eq!(vc.get(99), 0);
128 }
129
130 #[test]
131 fn test_happens_before() {
132 let mut a = VectorClock::new();
133 a.tick(1);
134 let mut b = VectorClock::new();
136 b.merge_and_tick(&a, 2);
137 assert_eq!(a.compare(&b), VectorClockOrder::HappensBefore);
139 assert_eq!(b.compare(&a), VectorClockOrder::HappensAfter);
140 }
141
142 #[test]
143 fn test_concurrent() {
144 let mut a = VectorClock::new();
145 a.tick(1);
146 let mut b = VectorClock::new();
147 b.tick(2);
148 assert_eq!(a.compare(&b), VectorClockOrder::Concurrent);
150 assert!(a.is_concurrent(&b));
151 }
152
153 #[test]
154 fn test_merge() {
155 let mut a = VectorClock::new();
156 a.tick(1);
157 a.tick(1); let mut b = VectorClock::new();
159 b.tick(2); b.merge(&a);
161 assert_eq!(b.get(1), 2);
163 assert_eq!(b.get(2), 1);
164 }
165
166 #[test]
167 fn test_equal_clocks() {
168 let mut a = VectorClock::new();
169 let mut b = VectorClock::new();
170 a.tick(1);
171 b.tick(1);
172 assert_eq!(a.compare(&b), VectorClockOrder::Equal);
173 }
174}