70 lines
1.8 KiB
Rust
70 lines
1.8 KiB
Rust
|
|
use std::collections::HashMap;
|
||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct VersionedValue {
|
||
|
|
pub value: Vec<u8>,
|
||
|
|
pub version: u64,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug, Clone, Default)]
|
||
|
|
pub struct GossipState {
|
||
|
|
entries: HashMap<String, VersionedValue>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl GossipState {
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self::default()
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Insert or update a key. Auto-increments the version for that key.
|
||
|
|
/// Returns the new version number.
|
||
|
|
pub fn set(&mut self, key: String, value: Vec<u8>) -> u64 {
|
||
|
|
let new_version = self
|
||
|
|
.entries
|
||
|
|
.get(&key)
|
||
|
|
.map_or(1, |existing| existing.version + 1);
|
||
|
|
self.entries.insert(
|
||
|
|
key,
|
||
|
|
VersionedValue {
|
||
|
|
value,
|
||
|
|
version: new_version,
|
||
|
|
},
|
||
|
|
);
|
||
|
|
new_version
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn get(&self, key: &str) -> Option<&VersionedValue> {
|
||
|
|
self.entries.get(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn entries(&self) -> &HashMap<String, VersionedValue> {
|
||
|
|
&self.entries
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn len(&self) -> usize {
|
||
|
|
self.entries.len()
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn is_empty(&self) -> bool {
|
||
|
|
self.entries.is_empty()
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Merge a remote state into this one. For each key, keep the entry
|
||
|
|
/// with the higher version (last-writer-wins). Returns the number of
|
||
|
|
/// entries that were updated.
|
||
|
|
pub fn merge(&mut self, remote: &GossipState) -> usize {
|
||
|
|
let mut updated = 0;
|
||
|
|
for (key, remote_val) in &remote.entries {
|
||
|
|
let dominated = match self.entries.get(key) {
|
||
|
|
Some(local_val) => remote_val.version > local_val.version,
|
||
|
|
None => true,
|
||
|
|
};
|
||
|
|
if dominated {
|
||
|
|
self.entries.insert(key.clone(), remote_val.clone());
|
||
|
|
updated += 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
updated
|
||
|
|
}
|
||
|
|
}
|