示例#1
0
        public void Propose(TValue value, int csn)
        {
            if (!isRunning)
            {
                return;
            }

            if (reProposers.ContainsKey(csn))
            {
                reProposers[csn].Kill();
                reProposers.Remove(csn);
            }

            numAcceptRequests[csn] = 0;
            Proposal <TValue> proposal = new Proposal <TValue>(csn, psn, value);

            reProposers.Add(csn, new NodeReProposer <TValue>(this.Propose, proposal));
            proposals[csn] = proposal;
            Broadcast(new PrepareRequestMessage(csn, psn));
            psn += _nodes.Count;
        }
示例#2
0
 public PrepareResponseMessage(int csn, int minPsn, Proposal <TValue> proposal)
 {
     this.proposal = proposal;
     this.minPsn   = minPsn;
     this.csn      = csn;
 }
示例#3
0
 public NodeReProposer(Action <TValue, int> propose, Proposal <TValue> proposal)
 {
     this.isRunning = true;
     this._propose  = propose;
     this.proposal  = proposal;
 }
示例#4
0
        /// <summary>
        /// Serialized Node Message Pump
        /// </summary>
        /// <param name="m"></param>
        private void Deliver(Message m)
        {
            lock (_nodeLock)
            {
                if (!isRunning)
                {
                    return;
                }

                if (m is HeartbeatMessage)
                {
                    // drop own heartbeats
                    if (m.Sender == this._location)
                    {
                        return;
                    }

                    _heartbeatObservers[m.Sender.getNum()].ResetTimeout();
                }
                else if (m is PrepareRequestMessage)
                // Acceptor
                {
                    PrepareRequestMessage prepareRequest = (PrepareRequestMessage)m;
                    int csn = prepareRequest.getCsn();
                    int psn = prepareRequest.getPsn();
                    if (currentCsn <= csn)
                    {
                        currentCsn = csn + 1;
                    }
                    Utility.WriteDebug("Got Prepare Request from " + prepareRequest.Sender + ": (" + csn + ", " + psn + ")");

                    // new minPsn
                    if (!minPsns.ContainsKey(csn) || minPsns[csn] < psn)
                    {
                        minPsns[csn] = psn;
                    }
                    // respond
                    Proposal <TValue> responseProposalAccepted      = maxAcceptedProposals.ContainsKey(csn) ? maxAcceptedProposals[csn] : null;
                    PrepareResponseMessage <TValue> prepareResponse = new PrepareResponseMessage <TValue>(csn, minPsns[csn], responseProposalAccepted);
                    prepareResponse.Sender = _location;
                    Unicast(prepareRequest.Sender, prepareResponse);
                    UpdateStableStorage();
                }
                else if (m is PrepareResponseMessage <TValue> )
                // Proposer
                {
                    PrepareResponseMessage <TValue> prepareResponse = (PrepareResponseMessage <TValue>)m;
                    Proposal <TValue> acceptedProposal = prepareResponse.getProposal();
                    int csn    = prepareResponse.getCsn();
                    int minPsn = prepareResponse.getMinPsn();
                    Proposal <TValue> proposal = proposals[csn];
                    if (currentCsn <= csn)
                    {
                        currentCsn = csn + 1;
                    }
                    Utility.WriteDebug("Got Prepare Response from " + prepareResponse.Sender + ": " + csn + ", " + minPsn + ", " + (acceptedProposal == null ? "None" : acceptedProposal.toString()));
                    if (!numAcceptRequests.ContainsKey(csn))
                    {
                        // ignore if already heard from a majority
                        return;
                    }
                    // if acceptors already accepted something higher, use it instead
                    if (acceptedProposal != null && acceptedProposal.getPsn() > proposal.getPsn())
                    {
                        proposal = acceptedProposal;
                    }
                    // if acceptors already promised something higher, use higher psn
                    if (minPsn > proposal.getPsn())
                    {
                        while (psn < prepareResponse.getMinPsn())
                        {
                            psn += _nodes.Count;
                        }
                        Propose(proposal.getValue(), proposal.getCsn());
                        return;
                    }
                    int n = numAcceptRequests[csn];
                    n++;

                    if (n > (_nodes.Count / 2))
                    // has heard from majority?
                    {
                        numAcceptRequests.Remove(csn);
                        if (reProposers.ContainsKey(csn))
                        {
                            reProposers[csn].Kill();
                            reProposers.Remove(csn);
                        }
                        AcceptRequestMessage <TValue> acceptRequest = new AcceptRequestMessage <TValue>(proposal);
                        Broadcast(acceptRequest);
                    }
                    else
                    {
                        numAcceptRequests[csn] = n;
                    }
                }
                else if (m is AcceptRequestMessage <TValue> ) // Acceptor
                {
                    AcceptRequestMessage <TValue> acceptRequest     = (AcceptRequestMessage <TValue>)m;
                    Proposal <TValue>             requestedProposal = acceptRequest.getProposal();
                    int csn = requestedProposal.getCsn();
                    int psn = requestedProposal.getPsn();
                    if (currentCsn <= csn)
                    {
                        currentCsn = csn + 1;
                    }
                    Utility.WriteDebug("Got Accept Request from " + acceptRequest.Sender + ": " + requestedProposal.toString());
                    if (psn < minPsns[csn])
                    {
                        return; // ignore
                    }
                    // "accept" the proposal

                    if (psn > minPsns[csn])
                    {
                        minPsns[csn] = psn;
                    }

                    maxAcceptedProposals[csn] = requestedProposal;
                    Utility.WriteDebug("Accepted: " + requestedProposal.toString());

                    // Notify Learners
                    AcceptNotificationMessage <TValue> acceptNotification = new AcceptNotificationMessage <TValue>(requestedProposal);
                    Broadcast(acceptNotification);
                    UpdateStableStorage();
                }
                else if (m is AcceptNotificationMessage <TValue> )
                // Learner
                {
                    AcceptNotificationMessage <TValue> acceptNotification = (AcceptNotificationMessage <TValue>)m;
                    Proposal <TValue> acceptedProposal = acceptNotification.Proposal;
                    int csn = acceptedProposal.getCsn();
                    if (currentCsn <= csn)
                    {
                        currentCsn = csn + 1;
                    }
                    Utility.WriteDebug("Got Accept Notification from " + acceptNotification.Sender + ": " + (acceptedProposal == null ? "None" : acceptedProposal.toString()));

                    // ignore if already learned
                    if (_chosenValues.ContainsKey(csn))
                    {
                        return;
                    }

                    if (!_numAcceptNotifications.ContainsKey(csn))
                    {
                        _numAcceptNotifications[csn] = 0;
                    }
                    int n = _numAcceptNotifications[csn];
                    n++;
                    if (n > (_nodes.Count / 2)) // has heard from majority?
                    {
                        _numAcceptNotifications.Remove(csn);
                        _chosenValues[csn] = acceptedProposal.getValue();
                        Utility.WriteDebug("Learned: " + acceptedProposal.getCsn() + ", " + acceptedProposal.getValue());
                        UpdateStableStorage();
                    }
                    else
                    {
                        _numAcceptNotifications[csn] = n;
                    }
                }
                else if (m is NewLeaderNotificationMessage) // Leader Election
                {
                    NewLeaderNotificationMessage newLeaderNotification = (NewLeaderNotificationMessage)m;
                    int newNum = newLeaderNotification.getNum();
                    Utility.WriteDebug("Got New Leader Notification from " + newLeaderNotification.Sender + ": " + newNum);
                    // am i new leader?
                    if (_location.getNum() == newNum)
                    {
                        BecomeLeader();
                    }
                    // find new leader, make others non-leaders
                    foreach (NodeLocation node in _nodes)
                    {
                        if (node.getNum() == newNum)
                        {
                            node.becomeLeader();
                        }
                        else
                        {
                            node.becomeNonLeader();
                        }
                    }
                }
                else
                {
                    Utility.WriteDebug("Unknown Message recieved", true);
                }
            }
        }
示例#5
0
 public AcceptNotificationMessage(Proposal <TValue> proposal)
 {
     this.proposal = proposal;
 }
示例#6
0
 public AcceptRequestMessage(Proposal <TValue> proposal)
 {
     this.proposal = proposal;
 }