1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::collections::HashMap;

use bincode::{deserialize, serialize};

use super::*;

/// Use Storage to plug this CASPaxos instance into an underlying store.
pub trait Storage: Clone {
    fn get_highest_seen(&mut self, key: Key) -> Ballot;
    fn get_accepted_ballot(&mut self, key: Key) -> Ballot;
    fn get_accepted_value(&mut self, key: Key) -> Option<Value>;
    fn set_highest_seen(&mut self, key: Key, ballot: Ballot);
    fn set_accepted_ballot(&mut self, key: Key, ballot: Ballot);
    fn set_accepted_value(&mut self, key: Key, value: Option<Value>);
}

const HIGHEST_SEEN_SUFFIX: u8 = 0;
const LAST_BALLOT_SUFFIX: u8 = 1;
const LAST_VALUE_SUFFIX: u8 = 2;

#[derive(Default, Clone)]
pub struct MemStorage {
    inner: HashMap<Key, Value>,
}

impl Storage for MemStorage {
    fn get_highest_seen(&mut self, mut k: Key) -> Ballot {
        k.push(HIGHEST_SEEN_SUFFIX);
        self.inner
            .get(&k)
            .cloned()
            .map(|v| deserialize(&v[..]).unwrap())
            .unwrap_or_else(|| Ballot::default())
    }
    fn get_accepted_ballot(&mut self, mut k: Key) -> Ballot {
        k.push(LAST_BALLOT_SUFFIX);
        self.inner
            .get(&k)
            .cloned()
            .map(|v| deserialize(&v[..]).unwrap())
            .unwrap_or_else(|| Ballot::default())
    }
    fn get_accepted_value(&mut self, mut k: Key) -> Option<Value> {
        k.push(LAST_VALUE_SUFFIX);
        self.inner.get(&k).cloned()
    }
    fn set_highest_seen(&mut self, mut k: Key, ballot: Ballot) {
        k.push(HIGHEST_SEEN_SUFFIX);
        let v = serialize(&ballot).unwrap();
        self.inner.insert(k, v);
    }
    fn set_accepted_ballot(&mut self, mut k: Key, ballot: Ballot) {
        k.push(LAST_BALLOT_SUFFIX);
        let v = serialize(&ballot).unwrap();
        self.inner.insert(k, v);
    }
    fn set_accepted_value(&mut self, mut k: Key, value: Option<Value>) {
        k.push(LAST_VALUE_SUFFIX);
        if let Some(v) = value {
            self.inner.insert(k, v);
        } else {
            self.inner.remove(&k);
        }
    }
}

#[derive(Clone)]
pub struct SledStorage {
    inner: sled::Tree,
}

impl SledStorage {
    pub fn new(tree: sled::Tree) -> SledStorage {
        SledStorage { inner: tree }
    }
}

impl Storage for SledStorage {
    fn get_highest_seen(&mut self, mut k: Key) -> Ballot {
        k.push(HIGHEST_SEEN_SUFFIX);
        self.inner
            .get(&k)
            .unwrap()
            .map(|v| deserialize(&v[..]).unwrap())
            .unwrap_or_else(|| Ballot::default())
    }
    fn get_accepted_ballot(&mut self, mut k: Key) -> Ballot {
        k.push(LAST_BALLOT_SUFFIX);
        self.inner
            .get(&k)
            .unwrap()
            .map(|v| deserialize(&v[..]).unwrap())
            .unwrap_or_else(|| Ballot::default())
    }
    fn get_accepted_value(&mut self, mut k: Key) -> Option<Value> {
        k.push(LAST_VALUE_SUFFIX);
        self.inner.get(&k).unwrap().map(|iv| iv.to_vec())
    }
    fn set_highest_seen(&mut self, mut k: Key, ballot: Ballot) {
        k.push(HIGHEST_SEEN_SUFFIX);
        let v = serialize(&ballot).unwrap();
        self.inner.insert(k, v).unwrap();
    }
    fn set_accepted_ballot(&mut self, mut k: Key, ballot: Ballot) {
        k.push(LAST_BALLOT_SUFFIX);
        let v = serialize(&ballot).unwrap();
        self.inner.insert(k, v).unwrap();
    }
    fn set_accepted_value(&mut self, mut k: Key, value: Option<Value>) {
        k.push(LAST_VALUE_SUFFIX);
        if let Some(v) = value {
            self.inner.insert(k, v).unwrap();
        } else {
            self.inner.remove(&k).unwrap();
        }
    }
}