logicaffeine_data/crdt/causal/
vclock.rs1use super::super::replica::ReplicaId;
6use super::super::Merge;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
15pub struct VClock {
16 entries: HashMap<ReplicaId, u64>,
17}
18
19impl VClock {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn increment(&mut self, replica: ReplicaId) -> u64 {
27 let entry = self.entries.entry(replica).or_insert(0);
28 *entry += 1;
29 *entry
30 }
31
32 pub fn get(&self, replica: ReplicaId) -> u64 {
34 *self.entries.get(&replica).unwrap_or(&0)
35 }
36
37 pub fn dominates(&self, other: &Self) -> bool {
41 for (&replica, &count) in &other.entries {
42 if self.get(replica) < count {
43 return false;
44 }
45 }
46 true
47 }
48
49 pub fn concurrent(&self, other: &Self) -> bool {
51 !self.dominates(other) && !other.dominates(self)
52 }
53
54 pub fn merge_vclock(&mut self, other: &Self) {
56 for (&replica, &count) in &other.entries {
57 let entry = self.entries.entry(replica).or_insert(0);
58 *entry = (*entry).max(count);
59 }
60 }
61
62 pub fn replicas(&self) -> impl Iterator<Item = &ReplicaId> {
64 self.entries.keys()
65 }
66}
67
68impl Merge for VClock {
69 fn merge(&mut self, other: &Self) {
70 self.merge_vclock(other);
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_vclock_new() {
80 let clock = VClock::new();
81 assert_eq!(clock.get(42), 0);
82 }
83
84 #[test]
85 fn test_vclock_increment() {
86 let mut clock = VClock::new();
87 assert_eq!(clock.increment(42), 1);
88 assert_eq!(clock.increment(42), 2);
89 assert_eq!(clock.get(42), 2);
90 }
91
92 #[test]
93 fn test_vclock_merge() {
94 let mut a = VClock::new();
95 let mut b = VClock::new();
96
97 a.increment(1);
98 a.increment(1);
99 b.increment(2);
100
101 a.merge(&b);
102
103 assert_eq!(a.get(1), 2);
104 assert_eq!(a.get(2), 1);
105 }
106
107 #[test]
108 fn test_vclock_dominates() {
109 let mut a = VClock::new();
110 let mut b = VClock::new();
111
112 a.increment(1);
113 a.increment(1);
114 b.increment(1);
115
116 assert!(a.dominates(&b));
117 assert!(!b.dominates(&a));
118 }
119
120 #[test]
121 fn test_vclock_concurrent() {
122 let mut a = VClock::new();
123 let mut b = VClock::new();
124
125 a.increment(1);
126 b.increment(2);
127
128 assert!(a.concurrent(&b));
129 }
130}