Exemplo n.º 1
0
        private void OnVoterConfirmation()
        {
            TransactionOperationContext context;

            if (_hasNewTopology.Lower())
            {
                ClusterTopology clusterTopology;
                using (_engine.ContextPool.AllocateOperationContext(out context))
                    using (context.OpenReadTransaction())
                    {
                        clusterTopology = _engine.GetTopology(context);
                    }
                if (clusterTopology.Contains(_engine.LeaderTag) == false)
                {
                    TaskExecutor.CompleteAndReplace(ref _newEntriesArrived);
                    _engine.SetNewState(RachisState.Passive, this, Term,
                                        "I was kicked out of the cluster and moved to passive mode");
                    return;
                }
                RefreshAmbassadors(clusterTopology);
            }

            var maxIndexOnQuorum = GetMaxIndexOnQuorum(VotersMajority);

            if (_lastCommit >= maxIndexOnQuorum ||
                maxIndexOnQuorum == 0)
            {
                return; // nothing to do here
            }
            bool changedFromLeaderElectToLeader;

            using (_engine.ContextPool.AllocateOperationContext(out context))
                using (context.OpenWriteTransaction())
                {
                    _lastCommit = _engine.GetLastCommitIndex(context);

                    if (_lastCommit >= maxIndexOnQuorum ||
                        maxIndexOnQuorum == 0)
                    {
                        return; // nothing to do here
                    }
                    if (_engine.GetTermForKnownExisting(context, maxIndexOnQuorum) < Term)
                    {
                        return;// can't commit until at least one entry from our term has been published
                    }
                    changedFromLeaderElectToLeader = _engine.TakeOffice();

                    maxIndexOnQuorum = _engine.Apply(context, maxIndexOnQuorum, this, Stopwatch.StartNew());

                    context.Transaction.Commit();

                    _lastCommit = maxIndexOnQuorum;
                }

            foreach (var kvp in _entries)
            {
                if (kvp.Key > _lastCommit)
                {
                    continue;
                }

                if (_entries.TryRemove(kvp.Key, out CommandState value))
                {
                    TaskExecutor.Execute(o =>
                    {
                        var tuple = (CommandState)o;
                        if (tuple.OnNotify != null)
                        {
                            tuple.OnNotify(tuple.TaskCompletionSource);
                            return;
                        }
                        tuple.TaskCompletionSource.TrySetResult((tuple.CommandIndex, tuple.Result));
                    }, value);
                }
            }

            if (_entries.Count != 0)
            {
                // we have still items to process, run them in 1 node cluster
                // and speed up the followers ambassadors if they can
                _newEntry.Set();
            }

            if (changedFromLeaderElectToLeader)
            {
                _engine.LeaderElectToLeaderChanged();
            }
        }