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; }
public PrepareResponseMessage(int csn, int minPsn, Proposal <TValue> proposal) { this.proposal = proposal; this.minPsn = minPsn; this.csn = csn; }
public NodeReProposer(Action <TValue, int> propose, Proposal <TValue> proposal) { this.isRunning = true; this._propose = propose; this.proposal = proposal; }
/// <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); } } }
public AcceptNotificationMessage(Proposal <TValue> proposal) { this.proposal = proposal; }
public AcceptRequestMessage(Proposal <TValue> proposal) { this.proposal = proposal; }