///|
pub(all) struct VectorClock {
entries : Array[ClockEntry]
}
///|
pub fn VectorClock::new() -> VectorClock {
{ entries: [] }
}
///|
pub fn VectorClock::from_entries(entries : Array[ClockEntry]) -> VectorClock {
let mut clock = VectorClock::new()
for entry in entries {
clock = clock.set(entry.node, entry.counter)
}
clock
}
///|
pub fn VectorClock::get(self : VectorClock, node : String) -> Int {
for entry in self.entries {
if entry.node == node {
return entry.counter
}
}
0
}
///|
pub fn VectorClock::set(
self : VectorClock,
node : String,
counter : Int,
) -> VectorClock {
let next = []
let mut found = false
for entry in self.entries {
if entry.node == node {
next.push(ClockEntry::new(node, counter))
found = true
} else {
next.push(entry)
}
}
if !found {
next.push(ClockEntry::new(node, counter))
}
{ entries: next }
}
///|
pub fn VectorClock::tick(self : VectorClock, node : String) -> VectorClock {
self.set(node, self.get(node) + 1)
}
///|
pub fn VectorClock::merge(
self : VectorClock,
other : VectorClock,
) -> VectorClock {
let mut merged = self
for entry in other.entries {
let local_counter = merged.get(entry.node)
if entry.counter > local_counter {
merged = merged.set(entry.node, entry.counter)
}
}
merged
}
///|
fn node_seen(nodes : Array[String], node : String) -> Bool {
for item in nodes {
if item == node {
return true
}
}
false
}
///|
fn all_nodes(left : VectorClock, right : VectorClock) -> Array[String] {
let nodes = []
for entry in left.entries {
if !node_seen(nodes, entry.node) {
nodes.push(entry.node)
}
}
for entry in right.entries {
if !node_seen(nodes, entry.node) {
nodes.push(entry.node)
}
}
nodes
}
///|
pub fn VectorClock::compare(
self : VectorClock,
other : VectorClock,
) -> CausalOrder {
let mut less = false
let mut greater = false
for node in all_nodes(self, other) {
let left = self.get(node)
let right = other.get(node)
if left < right {
less = true
} else if left > right {
greater = true
}
}
if less && greater {
Concurrent
} else if less {
Before
} else if greater {
After
} else {
Equal
}
}
///|
pub fn VectorClock::happens_before(
self : VectorClock,
other : VectorClock,
) -> Bool {
self.compare(other) == Before
}
///|
pub fn VectorClock::concurrent_with(
self : VectorClock,
other : VectorClock,
) -> Bool {
self.compare(other) == Concurrent
}