private static async Task <Result <VotingResult> > VoteAsync(IRaftClusterMember voter, long term, IAuditTrail <IRaftLogEntry> auditTrail, CancellationToken token)
            {
                var lastIndex = auditTrail.GetLastIndex(false);
                var lastTerm  = await auditTrail.GetTermAsync(lastIndex, token).ConfigureAwait(false);

                VotingResult result;

                try
                {
                    var response = await voter.VoteAsync(term, lastIndex, lastTerm, token).ConfigureAwait(false);

                    term   = response.Term;
                    result = response.Value ? VotingResult.Granted : VotingResult.Rejected;
                }
                catch (OperationCanceledException)
                {
                    result = VotingResult.Canceled;
                }
                catch (MemberUnavailableException)
                {
                    result = VotingResult.NotAvailable;
                    term   = -1L;
                }

                return(new Result <VotingResult>(term, result));
            }
Exemple #2
0
        //true if at least one entry from current term is stored on this node; otherwise, false
        private static async Task <Result <bool> > AppendEntriesAsync(IRaftClusterMember member, long commitIndex,
                                                                      long term,
                                                                      IAuditTrail <ILogEntry> transactionLog, ILogger logger, CancellationToken token)
        {
            var currentIndex = transactionLog.GetLastIndex(false);

            logger.ReplicationStarted(member.Endpoint, currentIndex);
            var precedingIndex = Math.Max(0, member.NextIndex - 1);
            var precedingTerm  = (await transactionLog.GetEntryAsync(precedingIndex).ConfigureAwait(false) ??
                                  transactionLog.First).Term;
            var entries = currentIndex >= member.NextIndex
                ? await transactionLog.GetEntriesAsync(member.NextIndex).ConfigureAwait(false)
                : Array.Empty <ILogEntry>();

            logger.ReplicaSize(member.Endpoint, entries.Count, precedingIndex, precedingTerm);
            //trying to replicate
            var result = await member
                         .AppendEntriesAsync(term, entries, precedingIndex, precedingTerm, commitIndex, token)
                         .ConfigureAwait(false);

            if (result.Value)
            {
                logger.ReplicationSuccessful(member.Endpoint, member.NextIndex);
                member.NextIndex.VolatileWrite(currentIndex + 1);
                //checks whether the at least one entry from current term is stored on this node
                result = result.SetValue(entries.Any(entry => entry.Term == term));
            }
            else
            {
                logger.ReplicationFailed(member.Endpoint, member.NextIndex.DecrementAndGet());
            }

            return(result);
        }
Exemple #3
0
            internal VotingState(IRaftClusterMember voter, long term, IAuditTrail <IRaftLogEntry> auditTrail, CancellationToken token)
            {
                Voter = voter;

                // ensure parallel requesting of votes
                Task = System.Threading.Tasks.Task.Run(() => VoteAsync(voter, term, auditTrail, token));
            }
Exemple #4
0
 internal Replicator(IRaftClusterMember member,
                     long commitIndex,
                     long term,
                     long precedingIndex,
                     long precedingTerm,
                     ILogger logger,
                     CancellationToken token)
 {
     this.member         = member;
     this.precedingIndex = precedingIndex;
     this.precedingTerm  = precedingTerm;
     this.commitIndex    = commitIndex;
     this.term           = term;
     this.logger         = logger;
     this.token          = token;
 }
 // TODO: Replace with required init properties in the next version of C#
 internal Replicator(
     IAuditTrail <IRaftLogEntry> auditTrail,
     IRaftClusterMember member,
     long commitIndex,
     long currentIndex,
     long term,
     long precedingIndex,
     long precedingTerm,
     ILogger logger,
     CancellationToken token)
 {
     this.auditTrail     = auditTrail;
     this.member         = member;
     this.precedingIndex = precedingIndex;
     this.precedingTerm  = precedingTerm;
     this.commitIndex    = commitIndex;
     this.currentIndex   = currentIndex;
     this.term           = term;
     this.logger         = logger;
     this.token          = token;
 }
 internal VotingState(IRaftClusterMember voter, long term, IAuditTrail <IRaftLogEntry> auditTrail, CancellationToken token)
 {
     Voter = voter;
     Task  = VoteAsync(voter, term, auditTrail, token);
 }
 bool ILocalMember.IsLeader(IRaftClusterMember member) => ReferenceEquals(Leader, member);
Exemple #8
0
 bool IHostingContext.IsLeader(IRaftClusterMember member) => ReferenceEquals(Leader, member);
 bool ILocalMember.IsLeader(IRaftClusterMember member) => throw new NotImplementedException();
Exemple #10
0
 ValueTask IPersistentState.UpdateVotedForAsync(IRaftClusterMember member)
 {
     votedFor = member;
     return(new ValueTask());
 }
Exemple #11
0
        bool IPersistentState.IsVotedFor(IRaftClusterMember member)
        {
            var lastVote = votedFor;

            return(lastVote is null || ReferenceEquals(lastVote, member));
        }