Beispiel #1
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);
        }
Beispiel #2
0
        internal static async ValueTask <bool> IsUpToDateAsync(this IAuditTrail <ILogEntry> auditTrail, long index, long term)
        {
            var localIndex = auditTrail.GetLastIndex(false);
            var localTerm  = (await auditTrail.GetEntryAsync(localIndex).ConfigureAwait(false) ?? auditTrail.First)
                             .Term;

            return(index >= localIndex && term >= localTerm);
        }
Beispiel #3
0
            private static async Task <Result <VotingResult> > VoteAsync(IRaftClusterMember voter, long term, IAuditTrail <ILogEntry> auditTrail, CancellationToken token)
            {
                var lastIndex = auditTrail.GetLastIndex(false);
                var lastTerm  = (await auditTrail.GetEntryAsync(lastIndex).ConfigureAwait(false) ?? auditTrail.First)
                                .Term;
                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;
                }
                return(new Result <VotingResult>(term, result));
            }
Beispiel #4
0
 internal static async ValueTask <bool> ContainsAsync(this IAuditTrail <ILogEntry> auditTrail, long index,
                                                      long term)
 => term == (await auditTrail.GetEntryAsync(index).ConfigureAwait(false) ?? auditTrail.First).Term;