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
118
119
120
121
122
123
124
125
126
127
//! Acceptor

use message::{AcceptedData, Message, Messenger, PromiseData};
use std::sync::Arc;

/// The Acceptors act as the fault-tolerant "memory" of the protocol. Acceptors
/// are collected into groups called Quorums. Any message sent to an Acceptor
/// must be sent to a Quorum of Acceptors. Any message received from an Acceptor
/// is ignored unless a copy is received from each Acceptor in a Quorum.
pub struct Acceptor<T> {
    /// `Acceptor`'s ID
    pub id: u64,
    /// The highest proposal number promised
    pub proposal_n: u64,
    /// The currently promised value
    pub value: Option<Arc<T>>,
    /// `Messenger` specifying communication with other nodes
    pub messenger: Option<Box<Messenger<T>>>,
}

impl<T> Acceptor<T> {
    /// Creates a new `Acceptor`.
    pub fn new(id: u64) -> Self {
        Self {
            id,
            proposal_n: 0,
            value: None,
            messenger: None,
        }
    }

    /// Receives a `Prepare` message from a `Proposer`.
    pub fn receive_prepare(&mut self, msg: &Message<T>) {
        if let Message::Prepare(data) = msg {
            if data.id > self.proposal_n {
                self.proposal_n = data.id;
                let promise = Message::Promise(PromiseData {
                    id: self.proposal_n,
                    value: self.value.clone(),
                    from: self.id,
                });
                if let Some(ref mut messenger) = self.messenger {
                    messenger.send_promise(promise);
                }
            }
        }
    }

    /// Receives an `Accept` message from a `Proposer`.
    pub fn receive_accept(&mut self, msg: &Message<T>) {
        if let Message::Accept(data) = msg {
            if data.id >= self.proposal_n {
                self.value = Some(data.value.clone());
                self.proposal_n = data.id;
                let accepted = Message::Accepted(AcceptedData {
                    id: self.proposal_n,
                    value: data.value.clone(),
                    from: self.id,
                });
                if let Some(ref mut messenger) = self.messenger {
                    messenger.send_accepted(accepted);
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use message::{AcceptData, ProposalData};

    #[test]
    fn acceptor_new() {
        let a: Acceptor<u64> = Acceptor::new(1);

        assert_eq!(a.id, 1);
        assert_eq!(a.proposal_n, 0);
        assert_eq!(a.value, None);
        assert!(a.messenger.is_none());
    }

    #[test]
    fn acceptor_receive_prepare() {
        let mut a: Acceptor<u64> = Acceptor::new(1);

        let msg = Message::Prepare(ProposalData { id: 8 });

        a.receive_prepare(&msg);

        assert_eq!(a.proposal_n, 8);

        // ignore proposals less than N
        let msg = Message::Prepare(ProposalData { id: 6 });

        a.receive_prepare(&msg);

        assert_eq!(a.proposal_n, 8);
    }

    #[test]
    fn acceptor_receive_accept() {
        let mut a: Acceptor<u64> = Acceptor::new(1);

        let msg = Message::Accept(AcceptData {
            id: 3,
            value: Arc::new(60),
        });

        a.receive_accept(&msg);

        assert_eq!(a.value, Some(Arc::new(60)));
        assert_eq!(a.proposal_n, 3);

        // ignore Accept messages less than N

        let msg = Message::Accept(AcceptData {
            id: 2,
            value: Arc::new(60),
        });

        a.receive_accept(&msg);

        assert_eq!(a.value, Some(Arc::new(60)));
        assert_eq!(a.proposal_n, 3);
    }
}