示例#1
0
        public void FindsMajorityPerfectly(int[] matchIndices, long majority)
        {
            var s = new VolatileLeaderState();

            foreach (var i in matchIndices)
            {
                s.SetMatchIndex(Guid.NewGuid(), i);
            }

            Assert.Equal(majority, s.GetMajorityMatchIndex());
        }
示例#2
0
        private void BecomeLeader()
        {
            _leaderAddress       = null;
            State.LastVotedForId = State.Id;
            _volatileLeaderState = new VolatileLeaderState();
            var peers = _peerManager.GetPeers().ToArray();

            foreach (var peer in peers)
            {
                TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] setting up indices for peer {peer.Address}");
                _volatileLeaderState.SetNextIndex(peer.Id, _logPersister.LastIndex + 1);
                _volatileLeaderState.SetMatchIndex(peer.Id, -1L);
            }

            SetupPeerAppendLogJobs(peers);
            OnRoleChanged(_role = Role.Leader);
        }
示例#3
0
        private async Task SendSnapshot(
            IRaftServer proxy,
            AsyncPolicy policy,
            Peer peer,
            long nextIndex,
            long matchIndex)
        {
            var      logOffset = LogPersister.LogOffset;
            var      term      = State.CurrentTerm;
            Snapshot ss;

            if (!SnapshotOperator.TryGetLastSnapshot(out ss))
            {
                throw new InvalidProgramException($"WE DO NOT HAVE A SNAPSHOT for client {peer.Address} whose nextIndex is {nextIndex} yet our LogOffset is {logOffset}");
            }

            if (ss.LastIncludedIndex + 1 < nextIndex)
            {
                throw new InvalidProgramException($"WE DO NOT HAVE A <<PROPER>> SNAPSHOT for client {peer.Address} whose nextIndex is {nextIndex} yet our LogOffset is {logOffset}. Snapshot was have ({ss.FullName}) is short {ss.LastIncludedIndex}");
            }

            // make a copy since it might be cleaned up or opened by another thread for another client
            var fileName = Path.GetTempFileName();

            File.Copy(ss.FullName, fileName, true);

            TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] About to send Snapshot copy file {fileName} to [{peer.ShortName}] and copy of {ss.FullName}.");

            using (var fs = new FileStream(fileName, FileMode.Open))
            {
                var start  = 0;
                var total  = 0;
                var length = fs.Length;
                var buffer = new byte[_settings.MaxSnapshotChunkSentInBytes];
                TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Snapshot copy file size is {length}. Location is {fileName} and copy of {ss.FullName}.");
                while (total < length)
                {
                    var count = fs.Read(buffer, 0, buffer.Length);
                    total += count;
                    var result = await proxy.InstallSnapshotAsync(new InstallSnapshotRequest()
                    {
                        CurrentTerm       = term,
                        Data              = count == buffer.Length ? buffer : buffer.Take(count).ToArray(),
                        LastIncludedIndex = ss.LastIncludedIndex,
                        LastIncludedTerm  = term,
                        IsDone            = total == length,
                        LeaderId          = State.Id,
                        Offset            = start
                    });

                    TheTrace.TraceInformation($"[{_meAsAPeer.ShortName}] Sent snapshot for peer {peer.Address} with {count} bytes totalling {total}.");

                    start += count;
                    if (result.CurrentTerm != term)
                    {
                        TheTrace.TraceWarning($"[{_meAsAPeer.ShortName}] I am sending snapshot but this peer {peer.Address} has term {result.CurrentTerm} vs my started term {term} and current term {State.CurrentTerm}.");
                    }
                }
            }

            _volatileLeaderState.SetMatchIndex(peer.Id, ss.LastIncludedIndex);
            _volatileLeaderState.SetNextIndex(peer.Id, ss.LastIncludedIndex + 1); // the rest will be done by sending logs
            File.Delete(fileName);
        }