Пример #1
0
 /// <summary>
 /// Attempts to commit changing the configuration if a consensus exists at this point.
 /// Otherwise a join is performed.
 /// If a consensus is lost before the desired configuration was reached, it is instantly applied.
 ///
 /// </summary>
 /// <param name="cfg"></param>
 public void ChangeConfiguration(Configuration cfg)
 {
     DoSerialized(() =>
     {
         if (IsInConsensus)
         {
             cfgChange   = new ConfigurationChange(cfg);
             cfgChangeAt = DateTime.Now;
             Schedule(cfgChange);
         }
         else
         {
             cfgChange = null;
             Join(cfg);
         }
     });
 }
Пример #2
0
        internal void Join(Configuration cfg)
        {
            List <Connection> doDispose = new List <Connection>();

            DoSerialized(() =>
            {
                if (cfgChange != null && cfgChange.NewCFG == cfg)
                {
                    LogMinorEvent("Recognized requested cfg");
                    cfgChange = null;
                }
                if (cfg == config)
                {
                    return;
                }

                LogEvent("Implementing consensus configuration " + cfg);
                int at;
                if (!cfg.ToIndex(MemberID, out at))
                {
                    LogError("Local member ID " + MemberID + " is not part of new consensus configuration " + cfg + ". Closing down node");
                    OnOutOfConfig(cfg);
                    Dispose();
                    throw new ArgumentException("Local member ID " + MemberID + " is not part of new consensus configuration " + cfg);
                }
                MemberID      = cfg.Members[at];
                MyLinearIndex = at;

                var newMembers = new Connection[cfg.Size];
                if (remoteMembers != null)
                {
                    foreach (var m in remoteMembers)
                    {
                        if (m == null)
                        {
                            continue;
                        }
                        int linear;
                        if (cfg.ToIndex(m.RemoteIdentifier, out linear) && m.IsActive == linear > MyLinearIndex && m.RemoteIdentifier == cfg.Members[linear])
                        {
                            if (at == linear)
                            {
                                throw new InvalidOperationException("Found self among remotes");
                            }
                            newMembers[linear] = m;
                        }
                        else
                        {
                            doDispose.Add(m);
                        }
                    }
                }
                config = cfg;
                for (int i = MyLinearIndex + 1; i < cfg.Size; i++)
                {
                    if (newMembers[i] == null)
                    {
                        newMembers[i] = new ActiveConnection(this, cfg.Members[i]);
                    }
                }
                remoteMembers = newMembers;

                if (IsLeader)
                {
                    if (!MemberID.CanBeLeader)
                    {
                        Yield();
                    }
                }
                else
                {
                    var l = leader as Connection;
                    int linear;
                    if (l != null && (!cfg.ToIndex(l.RemoteIdentifier, out linear) || !cfg.Members[linear].CanBeLeader))
                    {
                        Yield();
                    }
                }
            });

            foreach (var d in doDispose)
            {
                d.Dispose();
            }
        }