void AppendEntries(RaftMessage message) { //Ignore if message.term < term if (message.Term < currentTerm) { Console.Out.WriteLine("Old term detected. Discarding append entries."); return; } if (string.IsNullOrEmpty(message.Data)) { Console.Out.WriteLine("FOLLOWING ORDERS"); leader = message.Sender; state = RaftState.Follower; votedFor = null; electionTimeout = DateTime.UtcNow.AddMilliseconds(electionWaitPeriod); } else { var data = message.Data.Split('-'); var prevLogIndex = Int32.Parse(data[0]); var prevLogTerm = Int32.Parse(data[1]); var leaderCommitIndex = Int32.Parse(data[2]); //ignore if log doesn't contain an entry at prevLogIndex whos term is equal to prevLogTerm if (log[prevLogIndex] != null) { if (log[prevLogIndex].Term != prevLogTerm) { Console.Out.WriteLine("Incorrect term for previous log entry detected. Discarding append entries."); return; } } Console.Out.WriteLine("DOING WORK"); //If entry conflicts, delete entry and following entries /* * if (log[RaftLogEntry.Index] != null && log[RaftLogEntry.Index].Term != RaftLogEntry.Term) * { * var toBeDeleted = log.Where(x => x.Index >= RaftLogEntry.Index).Select(x => x.Index).ToList(); * foreach(var index in toBeDeleted) * { * log[index] = null; * } * } */ //Append all new entries to log /* * if(leaderCommitIndex > commitIndex) * { * commitIndex = Math.Min(leaderCommitIndex, lastNewEntry); * } */ } }
public BlockingCollection <RaftMessage> StartIncoming() { if (inStarted) { throw new Exception("You can only start the comms package input once."); } LocalHost = LocalIPAddress().ToString() + ":" + listenport; Task.Factory.StartNew(() => { string message; try { IPEndPoint localEndpoint = new IPEndPoint(LocalIPAddress(), listenport); IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, 0); UdpClient server = new UdpClient(localEndpoint); Console.Out.WriteLine("I'm listening on " + LocalHost); while (true) { message = Encoding.UTF8.GetString(server.Receive(ref remoteEndpoint)); Console.WriteLine("COM: Got message {0}", message); var dataParts = message.Split('|'); if (dataParts.Count() < 3) { continue; } var type = (RaftMessageType)Int32.Parse(dataParts[0]); var sender = dataParts[1]; var term = Int32.Parse(dataParts[2]); var data = (dataParts.Count() > 3 ? dataParts[3] : ""); var msg = new RaftMessage { Type = type, Term = term, Sender = sender, Data = data }; incoming.Add(msg); } } catch (Exception ex) { Console.Out.Write(ex); } }, TaskCreationOptions.LongRunning); inStarted = true; return(incoming); }
public void StartIncoming() { // ZMQ Context, server socket context = ZmqContext.Create(); LocalHost = LocalIPAddress() + ":" + listenport; Task.Factory.StartNew(() => { string message; try { ZmqSocket server = context.CreateSocket(ZeroMQ.SocketType.REP); server.Bind("tcp://" + LocalHost); Console.Out.WriteLine("I'm listening on " + LocalHost); while (true) { message = server.Receive(Encoding.Unicode); if (message.Equals("OVER")) { continue; } Console.WriteLine("COM: Got message {0}", message); var dataParts = message.Split('|'); if (dataParts.Count() < 2) { continue; } var type = (RaftMessageType)Int32.Parse(dataParts[0]); var sender = dataParts[1]; var data = (dataParts.Count() > 2 ? dataParts[2] : ""); var msg = new RaftMessage { Type = type, Sender = sender, Data = data }; incoming.Add(msg); server.Send("OVER", Encoding.UTF8); } } catch (Exception ex) { Console.Out.Write(ex); } }, TaskCreationOptions.LongRunning); }
private void Send(RaftMessageType type, string destination, string data) { var msg = new RaftMessage { Type = type, Term = currentTerm, Destination = destination, Data = data }; outputQueue.Add(msg); }
void Vote(RaftMessage message) { var requester = message.Sender; if (message.Term < currentTerm) { Send(RaftMessageType.Vote, requester, "0"); return; } var logData = message.Data.Split('-'); var lastLogIndex = Int32.Parse(logData[0]); var lastLogTerm = Int32.Parse(logData[1]); if (votedFor == null || (lastLogIndex >= lastApplied && (lastApplied == 0 ? true : log[lastApplied].Term >= lastLogTerm))) { Console.Out.WriteLine("I voted for " + requester); votedFor = requester; electionTimeout = DateTime.UtcNow.AddMilliseconds(electionWaitPeriod); Send(RaftMessageType.Vote, requester, "1"); } }
private void VoteReceived(RaftMessage message) { if (message.Data == "1") { if (state != RaftState.Leader) { var from = message.Sender; Console.Out.WriteLine("Got vote from " + from); remoteNodes[from].VoteGranted = true; //me + others = total / 2 + 1 = quora var votesForMe = 1 + remoteNodes.Values.Where(x => x.VoteGranted).Count(); var votesNeeded = Math.Floor((double)((1 + remoteNodes.Keys.Count())) / 2) + 1; Console.Out.WriteLine("I need " + votesNeeded + " votes. I have " + votesForMe + " votes"); if (votesForMe >= votesNeeded) { BecomeLeader(); } } } }
private void ProcessMessage(RaftMessage message) { //If any message has a bigger term, set term = message.term and become follower if (message.Term > currentTerm) { state = RaftState.Follower; currentTerm = message.Term; } switch (message.Type) { case RaftMessageType.Vote: VoteReceived(message); break; case RaftMessageType.RequestVote: Vote(message); break; case RaftMessageType.AppendEntries: AppendEntries(message); break; } }