예제 #1
0
        //When a new shard is added, do the following
        public void OnShardAdded(ShardInfo shard)
        {
            if (shard != null)
            {
                if (shard.Name != context.LocalShardName && _remoteShards != null && !_remoteShards.ContainsKey(shard.Name))
                {
                    if (_clusterConfigMgr != null)
                    {
                        _clusterConfigMgr.UpdateClusterConfiguration();
                        ShardConfiguration sConfig = _clusterConfigMgr.GetShardConfiguration(context.LocalShardName);
                        if (sConfig == null)
                        {
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Warn("ClusterManager.OnShardAdded() ", "The shard " + shard.Name + " does not exist in the configuration.");
                            }
                            return;
                        }

                        IShard remoteShard = new RemoteShard(new DualChannelFactory(), new ShardChannelFormatter(), context, _connectionRestoration);
                        remoteShard.Initialize(sConfig);
                        remoteShard.RegisterShardListener(Common.MiscUtil.CLUSTER_MANAGER, this);
                        lock (_remoteShards)
                        {
                            _remoteShards.Add(shard.Name, remoteShard);
                        }
                    }
                }
            }
        }
예제 #2
0
        public void Run()
        {
            LoggerManager.Instance.SetThreadContext(new LoggerContext()
            {
                ShardName = _context.LocalShardName != null ? _context.LocalShardName : "", DatabaseName = ""
            });
            _context.StatusLatch.WaitForAny(NodeStatus.Running);
            _startSignal.WaitOne();

            if (_context.ConfigurationSession != null)
            {
                ((OutProcConfigurationSession)_context.ConfigurationSession).RegisterListener(this);
            }

            while (_running)
            {
                try
                {
                    if (_node == null)
                    {
                        _clusterConfigMgr.UpdateClusterConfiguration();
                    }

                    if (_clusterConfigMgr != null)
                    {
                        ShardConfiguration sConfig = _clusterConfigMgr.GetShardConfiguration(_context.LocalShardName);
                        if (sConfig != null && sConfig.Servers != null)
                        {
                            _node = sConfig.Servers.GetServerNode(_context.LocalAddress.IpAddress.ToString());
                        }
                    }
                    if (_node == null && LoggerManager.Instance.ShardLogger != null &&
                        LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Warn("NodeToCSHeartbeatTask.Run() ", "Node " + _context.LocalAddress.ToString() +
                                                                " is not part of the configuration.");
                        return;
                    }
                    OperationId lastOpId = null;
                    if (_membershipManager != null && _membershipManager.LatestMembership != null && _membershipManager.LatestMembership.Primary != null && _membershipManager.LatestMembership.Primary.Name.Equals(_context.LocalAddress.IpAddress.ToString()))
                    {
                        lastOpId = _membershipManager.GetLastOperationId;
                    }
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    _heartbeatInterval =
                        _context.ConfigurationSession.ReportHeartbeat(_context.ClusterName, _context.LocalShardName,
                                                                      _node, _membershipManager.LatestMembership, lastOpId) * 1000;
                    watch.Stop();
                    _csStatus = ConnectivityStatus.Connected;
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("NodeToCSHeartbeatTask.Run() ", "Heartbeat sent to the CS at " +
                                                                 DateTime.Now.ToString() + " time taken to report heartbeat :" + watch.Elapsed.TotalSeconds);
                    }
                    if (_heartbeatInterval > 0 && (watch.Elapsed.TotalSeconds > _heartbeatInterval / 2))
                    {
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsErrorEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Error("NodeToCSHeartbeatTask.Run() ", "Heartbeat sent to the CS at " +
                                                                     DateTime.Now.ToString() + " time taken to report heartbeat :" + watch.Elapsed.TotalSeconds + " which is greater than half of the hb interval.");
                        }
                    }
                }
                catch (ThreadAbortException e)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsErrorEnabled && _nodeToCSThread != null)
                    {
                        LoggerManager.Instance.ShardLogger.Error(_nodeToCSThread.Name, "Task aborted.");
                    }
                    break;
                }
                //the following should only be done when a connection exception occurs.
                catch (ChannelException e)
                {
                    if (LoggerManager.Instance.ShardLogger != null)
                    {
                        if (LoggerManager.Instance.ShardLogger.IsErrorEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Error("NodeToCSHeartbeatTask.Run()  ", e.ToString());
                        }
                        if (LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("NodeToCSHeartbeatTask.Run() ",
                                                                     "On CS disconnected process of the membership manager begins execution at " +
                                                                     DateTime.Now.ToString());
                        }
                    }

                    _csStatus = ConnectivityStatus.NotConnected;
                    _membershipManager.OnCSDisconnected();
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("NodeToCSHeartbeatTask.Run() ", "The NodeToCS task paused at " +
                                                                 DateTime.Now.ToString());
                    }

                    //foreach (var cluster in ManagementServer.s_DbmNodeConfiguration.DbmClusters.ClustersConfigurations)
                    //{
                    //    string csIp = cluster.ConfigServers.Nodes[0].Name;
                    //    int csPort = cluster.ConfigServers.Nodes[0].Port;

                    //    BrokenConnectionInfo info = new BrokenConnectionInfo();
                    //    info.BrokenAddress = new Address(csIp, csPort);
                    //    info.SessionType = Common.Communication.SessionTypes.Management;

                    //    _connectionRestoration.RegisterListener(info, this,_context.LocalShardName);
                    //}


                    this.Pause();
                }
                catch (Exception e)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsErrorEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Error("NodeToCSHbTask.Run() General Exception: ",
                                                                 e.ToString());
                    }

                    if (e.Message.Contains("No configuration server is available to process the request"))
                    {
                        _csStatus = ConnectivityStatus.NotConnected;
                        _membershipManager.OnCSDisconnected();
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("NodeToCSHeartbeatTask.Run() ", "The NodeToCS task paused at " +
                                                                     DateTime.Now.ToString());
                        }
                        this.Pause();
                    }
                }
                Stopwatch sleepWatch = new Stopwatch();
                sleepWatch.Start();
                Thread.Sleep(_heartbeatInterval);
                _startSignal.WaitOne();
                sleepWatch.Stop();

                if (sleepWatch.Elapsed.TotalMilliseconds > (_heartbeatInterval + 2000))
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("NodeToCSHeartbeatTask.Run() ", "CS task waited for  " + sleepWatch.Elapsed.TotalSeconds);
                    }
                }
            }
        }
        public void TriggerElectionMechanism(Activity activity, Server server, LocalShardHeartbeatReporting heartbeatReport, Membership existingMembership)
        {
            LoggerManager.Instance.SetThreadContext(new LoggerContext()
            {
                ShardName = _context.LocalShardName != null ? _context.LocalShardName : "", DatabaseName = ""
            });
            if (existingMembership == null)
            {
                existingMembership = new Membership();
            }
            ShardConfiguration sConfig = null;

            //Get the shard configuration
            if (_clusterConfigMgr != null)
            {
                sConfig = _clusterConfigMgr.GetShardConfiguration(_context.LocalShardName);
            }
            IList <Address>      activeNodes       = null;
            MembershipChangeArgs args              = new MembershipChangeArgs();
            ServerNodes          staticServerNodes = null;

            if (sConfig == null || sConfig.Servers == null)
            {
                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                {
                    LoggerManager.Instance.ShardLogger.Warn("ElectionBasedMembershipStrategy.TiggerElectionMechanism() ", "The shard " + _context.LocalShardName + " does not exist in the configuration.");
                }
                return;
            }
            staticServerNodes = sConfig.Servers;
            ElectionResult result = null;

            if (heartbeatReport != null)
            {
                activeNodes = heartbeatReport.GetReportTable.Keys.ToList();
            }

            Address activityNode = null;

            if (server == null)
            {
                activityNode = _context.LocalAddress;
            }
            else
            {
                activityNode = server.Address;
            }

            switch (activity)
            {
            case Activity.NodeJoining:
                if (server == null)
                {
                    return;
                }
                //On node join, we need to get membership from the config server for the first time.
                Membership csMembership = _context.ConfigurationSession.GetMembershipInfo(_context.ClusterName, _context.LocalShardName);
                ServerNode joiningNode  = sConfig.Servers.GetServerNode(server.Address.IpAddress.ToString());
                // If the added node is configured while the cluster is up and running, do the following.
                if (joiningNode == null)
                {
                    if (_clusterConfigMgr != null)
                    {
                        _clusterConfigMgr.UpdateClusterConfiguration();
                        sConfig = _clusterConfigMgr.GetShardConfiguration(_context.LocalShardName);
                    }
                    if (sConfig == null)
                    {
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Warn("ElectionBasedMembershipStrategy.TriggerElectionMechanism() ", "The shard " + _context.LocalShardName + " does not exist in the configuration.");
                        }
                        return;
                    }
                    joiningNode = sConfig.Servers.GetServerNode(server.Address.IpAddress.ToString());
                }
                if (joiningNode == null)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Warn("ElectionBasedMembershipStrategy.TriggerElectionMechanism() ", "The node " + server.Address + " is not part of the configuration.");
                    }
                    return;
                }

                if (existingMembership == null || existingMembership.Servers == null || !existingMembership.Servers.Contains(joiningNode))
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("ElectBasedMemSt.TriggerElectMech", "Node joining activity triggered for " + activityNode);
                    }
                }
                bool        thisNodeIsPrimary = false;
                OperationId lastOpId          = null;

                if (heartbeatReport != null && heartbeatReport.GetReportTable.ContainsKey(server.Address))
                {
                    args.ServerName = _context.LocalAddress;
                    args.ElectionId = null;
                    args.ChangeType = MembershipChangeArgs.MembershipChangeType.NodeJoined;

                    if (server.Address.Equals(_context.LocalAddress))
                    {
                        _context.ConfigurationSession.ReportNodeJoining(_context.ClusterName, _context.LocalShardName, sConfig.Servers.GetServerNode(_context.LocalAddress.IpAddress.ToString()));

                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", server.Address + " reported its joining to the config server. ");
                        }

                        //if the primary is not null and the channel is not disconnected, it can be set here.
                        if ((existingMembership == null || existingMembership.Primary == null) && csMembership.Primary != null && _shard.ActiveChannelsList.Contains(new Server(new Address(csMembership.Primary.Name, sConfig.Port), Status.Initializing)) && ObeysMajorityRule(_shard.ActiveChannelsList.Count, sConfig.Servers.Nodes.Count))
                        {
                            args.ServerName = new Address(csMembership.Primary.Name, sConfig.Port);
                            args.ElectionId = csMembership.ElectionId;
                            args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimarySet;
                            //if the node which was lost comes back up before the CS or the nodes can declare it dead,
                            //it should resume its status as a primary. There should be no need for an election in this case.
                            if (args.ServerName.Equals(_context.LocalAddress))
                            {
                                thisNodeIsPrimary = true;
                            }
                        }
                    }

                    if (thisNodeIsPrimary)
                    {
                        if (csMembership.ElectionId != null && LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", "election_id: " + csMembership.ElectionId.Id + " election time :" + csMembership.ElectionId.ElectionTime);
                        }


                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", "I am already declared primary");
                        }
                        lastOpId = LastOperationId;
                        ChangeMembershipShardwide(args);
                    }
                    else
                    {
                        ((LocalShard)_shard).OnMembershipChanged(args);
                    }

                    if (server.Address.Equals(_context.LocalAddress))
                    {
                        ServerNode sNode = sConfig.Servers.GetServerNode(_context.LocalAddress.IpAddress.ToString());
                        if (sNode == null)
                        {
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Warn("ElectionBasedMembershipStrategy.TriggerElectionMechanism() ", "The node " + sNode.Name + " does not exist in the configuration.");
                            }
                            return;
                        }

                        _context.ConfigurationSession.ReportHeartbeat(_context.ClusterName, _context.LocalShardName, sNode, existingMembership, lastOpId);
                    }
                }
                else
                {
                    if (existingMembership.Primary != null && existingMembership.Primary.Name.Equals(server.Address.IpAddress.ToString()))
                    {
                        if (sConfig.Servers == null || sConfig.Servers.Nodes == null || !ObeysMajorityRule(activeNodes.Count, sConfig.Servers.Nodes.Count))
                        {
                            _context.ConfigurationSession.SetNodeStatus(_context.ClusterName, _context.LocalShardName, existingMembership.Primary, NodeRole.None);
                            args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimaryDemoted;
                            args.ServerName = _context.LocalAddress;
                            ChangeMembershipShardwide(args);
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", " Node addition activity occured. Primary node " + _context.LocalAddress.IpAddress.ToString() + " demoted.");
                            }
                            return;
                        }
                    }
                }

                break;

            case Activity.NodeLeaving:
                if (server == null)
                {
                    return;
                }
                bool hasMajority = ObeysMajorityRule(activeNodes.Count, staticServerNodes.Nodes.Count);
                args.ServerName = server.Address;
                args.ChangeType = MembershipChangeArgs.MembershipChangeType.NodeLeft;

                _clusterConfigMgr.UpdateClusterConfiguration();

                if (existingMembership.Primary != null)
                {
                    // if the existing primary is actually the node lost, we need to update the configuration.

                    if (existingMembership.Primary.Name == server.Address.IpAddress.ToString())
                    {
                        //if Primary leaves, it should be updated locally.
                        args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimaryLost;
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.TriggerElectMech", "Node leaving activity triggered for " + server.Address + " . Primary lost.");
                        }
                    }
                    else if (existingMembership.Primary.Name == _context.LocalAddress.IpAddress.ToString())     // if the existing primary is the local node, we need to check for possible demotion of the current primary.
                    {
                        if (!hasMajority)
                        {
                            _context.ConfigurationSession.SetNodeStatus(_context.ClusterName, _context.LocalShardName, existingMembership.Primary, NodeRole.None);
                            args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimaryDemoted;
                            args.ServerName = _context.LocalAddress;
                            ChangeMembershipShardwide(args);

                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.TriggerElectMech", " Node leaving activity occurred. Primary node " + _context.LocalAddress.IpAddress.ToString() + " demoted.");
                            }

                            return;
                        }
                    }
                }

                ((LocalShard)_shard).OnMembershipChanged(args);

                break;

            case Activity.GeneralElectionsTriggered:
            case Activity.TakeoverElectionsTriggered:
                // this is where the actual election mechanism takes place.

                //Step 1: if no node in the heartbeat table has a primary and there is no primary in the local node's membership, we proceed forward.
                //Else if there is a primary but this looks like the takeover election mechanism, we proceed along as well.
                if ((activity.Equals(Activity.GeneralElectionsTriggered) && !heartbeatReport.PrimaryExists() && existingMembership.Primary == null) || (activity.Equals(Activity.TakeoverElectionsTriggered) && heartbeatReport.PrimaryExists()))
                {
                    //Step 2: we verify that this node has a majority of the shard nodes connected to it.
                    if (activeNodes != null && ObeysMajorityRule(activeNodes.Count, staticServerNodes.Nodes.Count))
                    {
                        //Step 3: Perform the initial sanity check. (Speculative phase)
                        if (ShouldIInitiateElection(heartbeatReport, activity))
                        {
                            if (existingMembership != null && existingMembership.Primary != null && activity == Activity.GeneralElectionsTriggered)
                            {
                                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                                {
                                    LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", "A primary has already been selected for "
                                                                            + _context.LocalShardName + " hence exiting the election mechanism.");
                                }
                                return;
                            }
                            //Step 4: The elections take place in real. (Authoritative Phase)
                            result = HoldElection(heartbeatReport, activity);
                            if (result != null)
                            {
                                if (result.PollingResult == ElectionResult.Result.PrimarySelected)
                                {
                                    //if the shard is undergoing the takeover election mechanism, the old primary needs to
                                    //be demoted first.
                                    bool oldPrimaryDemoted = false;
                                    if (activity == Activity.TakeoverElectionsTriggered)
                                    {
                                        MembershipChangeArgs args2 = new MembershipChangeArgs();
                                        args2.ChangeType = MembershipChangeArgs.MembershipChangeType.ForcefullyDemotePrimary;
                                        args2.ServerName = _context.LocalAddress;
                                        args2.ElectionId = existingMembership.ElectionId;

                                        Message msg = new Message();
                                        msg.Payload       = args2;
                                        msg.MessageType   = MessageType.MembershipOperation;
                                        msg.NeedsResponse = true;
                                        ShardRequestBase <bool> request = _shard.CreateUnicastRequest <bool>(new Server(new Address(existingMembership.Primary.Name, sConfig.Port), Status.Running), msg);
                                        IAsyncResult            result2 = request.BeginExecute();
                                        oldPrimaryDemoted = request.EndExecute(result2);
                                    }
                                    //Submit the result to the CS.
                                    if (activity == Activity.GeneralElectionsTriggered || (activity == Activity.TakeoverElectionsTriggered && oldPrimaryDemoted))
                                    {
                                        _context.ConfigurationSession.SubmitElectionResult(_context.ClusterName.ToLower(), _context.LocalShardName.ToLower(), result);
                                    }
                                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                                    {
                                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.TriggerElectMech", "Election result submitted for shard " + _context.LocalShardName.ToString());
                                    }

                                    _context.ElectionResult = result;
                                    args.ServerName         = _context.LocalAddress;
                                    args.ElectionId         = result.ElectionId;
                                    args.ChangeType         = MembershipChangeArgs.MembershipChangeType.PrimarySelected;
                                    //Once, the result is submitted, inform the shard nodes.
                                    ChangeMembershipShardwide(args);
                                    _context.ConfigurationSession.ReportHeartbeat(_context.ClusterName, _context.LocalShardName, result.ElectedPrimary, existingMembership, LastOperationId);
                                }
                                //Finally, end this round of elections.
                                _context.ConfigurationSession.EndElection(_context.ClusterName, _context.LocalShardName, result.ElectionId);
                            }
                        }
                    }
                }

                break;

            case Activity.CSDisconnected:
                //this is called whenever a node loses connection with the config server.

                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                {
                    LoggerManager.Instance.ShardLogger.Debug("ElectionBasedMembershipStrategy.TriggerElectionMechanism() ", "Config Server disconnected. ");
                }
                //if the number of configured nodes are even and the primary loses connection with the CS, it needs to demote itself.
                if (existingMembership != null && existingMembership.Primary != null && existingMembership.Primary.Name == _context.LocalAddress.IpAddress.ToString() && staticServerNodes.Nodes.Count % 2 == 0)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.TriggerElectMech", " Connection of the node " + _context.LocalAddress.ToString() + " with the config server is lost.");
                    }

                    args.ServerName = _context.LocalAddress;
                    args.ElectionId = existingMembership.ElectionId;
                    args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimaryDemoted;
                    ChangeMembershipShardwide(args);
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", " Primary node " + _context.LocalAddress.IpAddress.ToString() + " demoted because the primary lost connection with the CS.");
                    }
                }
                break;

            case Activity.ForcefulPrimaryDemotion:
                if (existingMembership != null && existingMembership.Primary != null && existingMembership.Primary.Name == _context.LocalAddress.IpAddress.ToString())
                {
                    _context.ConfigurationSession.SetNodeStatus(_context.ClusterName, _context.LocalShardName, existingMembership.Primary, NodeRole.None);

                    args.ChangeType = MembershipChangeArgs.MembershipChangeType.PrimaryDemoted;
                    args.ServerName = _context.LocalAddress;
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Info("electBasedMemSt.TriggerElectMech", "Primary node " + _context.LocalAddress.IpAddress.ToString() + " demoted in order to complete the take over election mechanism. ");
                    }

                    ((LocalShard)_shard).OnMembershipChanged(args);
                }
                break;
            }
        }
예제 #4
0
        public bool OnMembershipChanged(MembershipChangeArgs args)
        {
            if (args != null)
            {
                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                {
                    LoggerManager.Instance.ShardLogger.Debug("LocalShard.OnMembershipChanged()", "Membership change type: " + args.ChangeType);
                }

                switch (args.ChangeType)
                {
                case MembershipChangeArgs.MembershipChangeType.PrimarySet:
                case MembershipChangeArgs.MembershipChangeType.PrimarySelected:
                    if (args.ServerName != null)
                    {
                        if (args.ServerName.Equals(context.LocalAddress))
                        {
                            lock (_mutexOnnodeRole)
                            {
                                NodeRole = Common.Configuration.Services.NodeRole.Primary;
                            }
                        }
                        else
                        {
                            lock (_mutexOnnodeRole)
                            {
                                if (NodeRole != NodeRole.Intermediate)
                                {
                                    NodeRole = Common.Configuration.Services.NodeRole.Secondary;
                                }
                            }
                        }
                        Primary = new Server(args.ServerName, Status.Running);

                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled && args.ElectionId != null)
                        {
                            LoggerManager.Instance.ShardLogger.Info("LocalShard.OnMembershipChanged()", "This term's election id is: " + args.ElectionId.Id);
                        }


                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                        {
                            if (args.ChangeType.Equals(MembershipChangeArgs.MembershipChangeType.PrimarySet))
                            {
                                LoggerManager.Instance.ShardLogger.Info("LocalShard.OnMembershipChanged()", "Node " + args.ServerName.IpAddress.ToString() + " set as the primary node for the shard.");
                            }
                            else if (args.ChangeType.Equals(MembershipChangeArgs.MembershipChangeType.PrimarySelected))
                            {
                                LoggerManager.Instance.ShardLogger.Info("LocalShard.OnMembershipChanged()", "Node " + args.ServerName.IpAddress.ToString() + " selected as the primary node for the shard.");
                            }
                        }

                        AppUtil.LogEvent(AppUtil.EventLogSource, string.Format("Node {0} is selected as primary for shard \"{1}\"", args.ServerName.ToString(), context.LocalShardName),
                                         EventLogEntryType.Information, EventCategories.Information, EventID.PrimaySelected);
                    }
                    break;

                case MembershipChangeArgs.MembershipChangeType.PrimaryLost:
                case MembershipChangeArgs.MembershipChangeType.PrimaryDemoted:
                case MembershipChangeArgs.MembershipChangeType.NodeLeft:

                    if (args.ServerName != null && Primary != null && args.ServerName.Equals(Primary.Address))
                    {
                        lock (_mutexOnnodeRole)
                        {
                            if (NodeRole != NodeRole.Intermediate)
                            {
                                NodeRole = Common.Configuration.Services.NodeRole.None;
                            }
                        }
                        Primary = null;

                        if (args.ServerName != null)
                        {
                            if (args.ChangeType.Equals(MembershipChangeArgs.MembershipChangeType.PrimaryDemoted))
                            {
                                AppUtil.LogEvent(AppUtil.EventLogSource, string.Format("Primary Node {0} is demoted for shard \"{1}\"", args.ServerName.ToString(), context.LocalShardName),
                                                 EventLogEntryType.Warning, EventCategories.Warning, EventID.PrimaryLost);

                                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                                {
                                    LoggerManager.Instance.ShardLogger.Warn("LocalShard.OnMembershipChanged()", "The primary " + args.ServerName.ToString() + " is demoted.");
                                }
                            }

                            else if (args.ChangeType.Equals(MembershipChangeArgs.MembershipChangeType.PrimaryLost))
                            {
                                AppUtil.LogEvent(AppUtil.EventLogSource, string.Format("Connection with the primary node {0} lost \"{1}\"", args.ServerName.ToString(), context.LocalShardName),
                                                 EventLogEntryType.Warning, EventCategories.Warning, EventID.PrimaryLost);
                                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                                {
                                    LoggerManager.Instance.ShardLogger.Warn("LocalShard.OnMembershipChanged()", "The primary " + args.ServerName.ToString() + " is lost.");
                                }
                            }
                        }
                    }

                    _clusterConfigMgr.UpdateClusterConfiguration();
                    if (args.ServerName != null)
                    {
                        ShardConfiguration sConfig = null;
                        if (_clusterConfigMgr != null && _clusterConfigMgr.LatestConfiguration != null && _clusterConfigMgr.LatestConfiguration.Deployment != null)
                        {
                            sConfig = _clusterConfigMgr.LatestConfiguration.Deployment.GetShardConfiguration(context.LocalShardName);
                        }
                        {
                            ServerNode node = null;
                            if (sConfig != null && sConfig.Servers != null)
                            {
                                node = sConfig.Servers.GetServerNode(args.ServerName.IpAddress.ToString());
                            }
                            if (node == null)
                            {
                                if (_connectionRestoration != null)
                                {
                                    BrokenConnectionInfo info = new BrokenConnectionInfo();
                                    info.BrokenAddress = args.ServerName;
                                    info.SessionType   = SessionTypes.Shard;
                                    _connectionRestoration.UnregisterListener(info);
                                }
                            }
                        }
                    }
                    break;

                case MembershipChangeArgs.MembershipChangeType.TimeoutOnRestrictedPrimary:
                    return(_membershipManager.AbortTakeoverMechanismTask(args));

                case MembershipChangeArgs.MembershipChangeType.ForcefullyDemotePrimary:
                    return(_membershipManager.OnForcefulPrimaryDemotion(args));
                }

                if (_membershipManager != null)
                {
                    _membershipManager.UpdateLocalMembership(args);
                    if (context != null && context.DatabasesManager != null &&
                        (args.ChangeType == MembershipChangeArgs.MembershipChangeType.PrimarySet ||
                         (args.ChangeType == MembershipChangeArgs.MembershipChangeType.PrimarySelected)))
                    {
                        context.DatabasesManager.ElectionResult = _membershipManager.LatestMembership.ElectionId;
                        context.ElectionResult            = new ElectionResult();
                        context.ElectionResult.ElectionId = _membershipManager.LatestMembership.ElectionId;
                    }

                    DatabaseMessage primaryChangedMessage = new DatabaseMessage();
                    primaryChangedMessage.OpCode = OpCode.PrimaryChanged;
                    IShardListener listener = _shardListeners[Common.MiscUtil.CLUSTER_MANAGER];
                    listener.OnMessageReceived(primaryChangedMessage, new Server(context.LocalAddress, Status.Running));
                }
            }
            return(false);
        }