//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); } } } } }
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; } }
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); }