internal void Schedule(CommitID cID, ICommitable entry) { serialLock.AssertIsLockedByMe(); if (state == State.Leader) { foreach (var l in log) { if (l.Entry.CommitID == cID) { LogMinorEvent("Already in log: " + entry + ". Ignoring"); return; } } LogMinorEvent("Issuing " + entry); PrivateEntry p = new PrivateEntry(new LogEntry(cID, currentTerm, entry)); if (DebugState != null) { DebugState.SignalSignalAppendAttempt(log.Count, p.Entry.Term); } if (CommitIndex == log.Count) { lastCommit = DateTime.Now; } log.Add(p); //add local Broadcast(new AppendEntries(this, p.Entry)); //transport remote ForeachConnection(c => c.ConsensusState.AppendTimeout = GetAppendMessageTimeout()); ReCheckCommitment(); } else { var cp = leader as Connection; if (cp != null) { LogMinorEvent("Dispatching " + entry + " to " + leader); cp.Dispatch(new CommitEntry(cID, currentTerm, entry)); } else { LogEvent("Received message out of consensus. Logging " + entry); //dispatchQueue.Enqueue(Helper.Tuple(cID, entry)); } } }
private void CommitTo(int newCommitCount) { serialLock.AssertIsLockedByMe(); try { if (commitCount < newCommitCount) { lastCommit = DateTime.Now; LogMinorEvent("Committing " + commitCount + ".." + newCommitCount + ", history length " + log.Count); for (int i = commitCount; i < newCommitCount; i++) { PrivateEntry e = log[i]; if (e == null) { LogMinorEvent("Skipping removed entry at #" + i); } else { if (DebugState != null) { DebugState.SignalExecution(i, e.Entry.Term, this); } if (!e.WasExecuted) { commitCount = Math.Max(commitCount, i + 1); LogMinorEvent("Executing " + e.Entry); e.Execute(this); committed.TryRemove(e.Entry.CommitID); } } } //Debug.Assert(commitCount == newCommitCount); if (IsLeader) { Broadcast(new AppendEntries(this)); nextActionAt = NextHeartbeat; } } } catch (Exception ex) { } }