2020-11-20 20:15:24 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use garage_util::data::*;
|
|
|
|
|
|
|
|
pub trait CRDT {
|
|
|
|
fn merge(&mut self, other: &Self);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> CRDT for T
|
2020-11-20 22:01:12 +00:00
|
|
|
where
|
|
|
|
T: Ord + Clone,
|
|
|
|
{
|
2020-11-20 20:15:24 +00:00
|
|
|
fn merge(&mut self, other: &Self) {
|
|
|
|
if other > self {
|
|
|
|
*self = other.clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- LWW Register ----
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
2020-11-20 22:01:12 +00:00
|
|
|
pub struct LWW<T> {
|
2020-11-20 20:15:24 +00:00
|
|
|
ts: u64,
|
|
|
|
v: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> LWW<T>
|
2020-11-20 22:01:12 +00:00
|
|
|
where
|
|
|
|
T: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + PartialEq + CRDT,
|
2020-11-20 20:15:24 +00:00
|
|
|
{
|
|
|
|
pub fn new(value: T) -> Self {
|
|
|
|
Self {
|
|
|
|
ts: now_msec(),
|
|
|
|
v: value,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn migrate_from_raw(ts: u64, value: T) -> Self {
|
2020-11-20 22:01:12 +00:00
|
|
|
Self { ts, v: value }
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
pub fn update(&mut self, new_value: T) {
|
|
|
|
self.ts = std::cmp::max(self.ts + 1, now_msec());
|
|
|
|
self.v = new_value;
|
|
|
|
}
|
|
|
|
pub fn get(&self) -> &T {
|
|
|
|
&self.v
|
|
|
|
}
|
2020-11-20 22:01:12 +00:00
|
|
|
pub fn get_mut(&mut self) -> &mut T {
|
|
|
|
&mut self.v
|
|
|
|
}
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> CRDT for LWW<T>
|
2020-11-20 22:01:12 +00:00
|
|
|
where
|
|
|
|
T: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + PartialEq + CRDT,
|
2020-11-20 20:15:24 +00:00
|
|
|
{
|
|
|
|
fn merge(&mut self, other: &Self) {
|
|
|
|
if other.ts > self.ts {
|
|
|
|
self.ts = other.ts;
|
|
|
|
self.v = other.v.clone();
|
|
|
|
} else if other.ts == self.ts {
|
|
|
|
self.v.merge(&other.v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- Boolean (true as absorbing state) ----
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
|
|
|
|
pub struct Bool(bool);
|
|
|
|
|
|
|
|
impl Bool {
|
|
|
|
pub fn new(b: bool) -> Self {
|
|
|
|
Self(b)
|
|
|
|
}
|
|
|
|
pub fn set(&mut self) {
|
|
|
|
self.0 = true;
|
|
|
|
}
|
|
|
|
pub fn get(&self) -> bool {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CRDT for Bool {
|
|
|
|
fn merge(&mut self, other: &Self) {
|
|
|
|
self.0 = self.0 || other.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- LWW Map ----
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
2020-11-20 22:01:12 +00:00
|
|
|
pub struct LWWMap<K, V> {
|
2020-11-20 20:15:24 +00:00
|
|
|
vals: Vec<(K, u64, V)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<K, V> LWWMap<K, V>
|
2020-11-20 22:01:12 +00:00
|
|
|
where
|
|
|
|
K: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + PartialEq + Ord,
|
|
|
|
V: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + PartialEq + Ord,
|
2020-11-20 20:15:24 +00:00
|
|
|
{
|
|
|
|
pub fn new() -> Self {
|
2020-11-20 22:01:12 +00:00
|
|
|
Self { vals: vec![] }
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
pub fn migrate_from_raw_item(k: K, ts: u64, v: V) -> Self {
|
2020-11-20 22:01:12 +00:00
|
|
|
Self {
|
2020-11-20 20:15:24 +00:00
|
|
|
vals: vec![(k, ts, v)],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn take_and_clear(&mut self) -> Self {
|
|
|
|
let vals = std::mem::replace(&mut self.vals, vec![]);
|
2020-11-20 22:01:12 +00:00
|
|
|
Self { vals }
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
self.vals.clear();
|
|
|
|
}
|
|
|
|
pub fn update_mutator(&self, k: K, new_v: V) -> Self {
|
2020-11-20 22:01:12 +00:00
|
|
|
let new_vals = match self.vals.binary_search_by(|(k2, _, _)| k2.cmp(&k)) {
|
2020-11-20 20:15:24 +00:00
|
|
|
Ok(i) => {
|
|
|
|
let (_, old_ts, _) = self.vals[i];
|
2020-11-20 22:01:12 +00:00
|
|
|
let new_ts = std::cmp::max(old_ts + 1, now_msec());
|
2020-11-20 20:15:24 +00:00
|
|
|
vec![(k, new_ts, new_v)]
|
|
|
|
}
|
2020-11-20 22:01:12 +00:00
|
|
|
Err(_) => vec![(k, now_msec(), new_v)],
|
2020-11-20 20:15:24 +00:00
|
|
|
};
|
2020-11-20 22:01:12 +00:00
|
|
|
Self { vals: new_vals }
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
pub fn get(&self, k: &K) -> Option<&V> {
|
2020-11-20 22:01:12 +00:00
|
|
|
match self.vals.binary_search_by(|(k2, _, _)| k2.cmp(&k)) {
|
2020-11-20 20:15:24 +00:00
|
|
|
Ok(i) => Some(&self.vals[i].2),
|
2020-11-20 22:01:12 +00:00
|
|
|
Err(_) => None,
|
2020-11-20 20:15:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn items(&self) -> &[(K, u64, V)] {
|
|
|
|
&self.vals[..]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<K, V> CRDT for LWWMap<K, V>
|
2020-11-20 22:01:12 +00:00
|
|
|
where
|
|
|
|
K: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + Ord,
|
|
|
|
V: Serialize + for<'de> Deserialize<'de> + Clone + core::fmt::Debug + CRDT,
|
2020-11-20 20:15:24 +00:00
|
|
|
{
|
|
|
|
fn merge(&mut self, other: &Self) {
|
|
|
|
for (k, ts2, v2) in other.vals.iter() {
|
2020-11-20 22:01:12 +00:00
|
|
|
match self.vals.binary_search_by(|(k2, _, _)| k2.cmp(&k)) {
|
2020-11-20 20:15:24 +00:00
|
|
|
Ok(i) => {
|
2020-11-20 22:01:12 +00:00
|
|
|
let (_, ts1, _v1) = &self.vals[i];
|
2020-11-20 20:15:24 +00:00
|
|
|
if ts2 > ts1 {
|
|
|
|
self.vals[i].1 = *ts2;
|
|
|
|
self.vals[i].2 = v2.clone();
|
|
|
|
} else if ts1 == ts2 {
|
|
|
|
self.vals[i].2.merge(&v2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(i) => {
|
|
|
|
self.vals.insert(i, (k.clone(), *ts2, v2.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|