private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args) { if (!args.NewServerDescription.Type.IsReplicaSetMember()) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type))); } if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost) { return(clusterDescription.WithServerDescription(args.NewServerDescription)); } if (_replicaSetName == null) { _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name; } if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName))); } clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription); clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription); if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary && args.OldServerDescription.Type != ServerType.ReplicaSetPrimary) { var currentPrimaryEndPoints = clusterDescription.Servers .Where(x => x.Type == ServerType.ReplicaSetPrimary) .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint)) .Select(x => x.EndPoint) .ToList(); if (currentPrimaryEndPoints.Count > 0) { lock (_serversLock) { var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint)); foreach (var currentPrimary in currentPrimaries) { // kick off the server to invalidate itself currentPrimary.Invalidate(); // set it to disconnected in the cluster clusterDescription = clusterDescription.WithServerDescription( new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint)); } } } } return(clusterDescription); }
private void ServerDescriptionChanged(object sender, ServerDescriptionChangedEventArgs args) { var oldClusterDescription = Description; ClusterDescription newClusterDescription = oldClusterDescription; var newServerDescription = args.NewServerDescription; if (newServerDescription.State == ServerState.Disconnected) { newClusterDescription = Description .WithServerDescription(newServerDescription); } else { var determinedClusterType = DetermineClusterType(newServerDescription); if (oldClusterDescription.Type == ClusterType.Unknown) { newClusterDescription = newClusterDescription .WithType(determinedClusterType) .WithServerDescription(newServerDescription); } else if (determinedClusterType != oldClusterDescription.Type) { newClusterDescription = newClusterDescription .WithoutServerDescription(newServerDescription.EndPoint); } else { newClusterDescription = newClusterDescription .WithServerDescription(newServerDescription); } } UpdateClusterDescription(newClusterDescription); }
private ClusterDescription ProcessStandaloneChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args) { if (Settings.EndPoints.Count > 1) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "Cluster was provided with multiple endpoints, one of which is a standalone.")); } if (args.NewServerDescription.Type != ServerType.Standalone) { return(clusterDescription.WithServerDescription( new ServerDescription(args.NewServerDescription.ServerId, args.NewServerDescription.EndPoint))); } else { return(clusterDescription.WithServerDescription(args.NewServerDescription)); } }
private ClusterDescription ProcessShardedChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args) { if (args.NewServerDescription.Type != ServerType.ShardRouter) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "Server is not a shard router.")); } return(clusterDescription.WithServerDescription(args.NewServerDescription)); }
private ClusterDescription EnsureServer(ClusterDescription clusterDescription, EndPoint endPoint, List <IClusterableServer> newServers) { if (_state.Value == State.Disposed) { return(clusterDescription); } IClusterableServer server; Stopwatch stopwatch = new Stopwatch(); lock (_serversLock) { if (_servers.Any(n => EndPointHelper.Equals(n.EndPoint, endPoint))) { return(clusterDescription); } if (_addingServerEventHandler != null) { _addingServerEventHandler(new ClusterAddingServerEvent(ClusterId, endPoint)); } stopwatch.Start(); server = CreateServer(endPoint); server.DescriptionChanged += ServerDescriptionChangedHandler; _servers.Add(server); newServers.Add(server); } clusterDescription = clusterDescription.WithServerDescription(server.Description); stopwatch.Stop(); if (_addedServerEventHandler != null) { _addedServerEventHandler(new ClusterAddedServerEvent(server.ServerId, stopwatch.Elapsed)); } return(clusterDescription); }
private ClusterDescription ProcessStandaloneChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args) { if (args.NewServerDescription.Type != ServerType.Unknown) { if (args.NewServerDescription.Type == ServerType.Standalone) { foreach (var endPoint in clusterDescription.Servers.Select(s => s.EndPoint).ToList()) { if (!EndPointHelper.Equals(endPoint, args.NewServerDescription.EndPoint)) { clusterDescription = RemoveServer(clusterDescription, endPoint, "Removing all other end points once a standalone is discovered."); } } } else { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "Server is not a standalone server.")); } } return(clusterDescription.WithServerDescription(args.NewServerDescription)); }
private ClusterDescription EnsureServer(ClusterDescription clusterDescription, EndPoint endPoint) { if (_state.Value == State.Disposed) { return(clusterDescription); } IClusterableServer server; Stopwatch stopwatch = new Stopwatch(); lock (_serversLock) { if (_servers.Any(n => n.EndPoint.Equals(endPoint))) { return(clusterDescription); } if (Listener != null) { Listener.ClusterBeforeAddingServer(ClusterId, endPoint); } stopwatch.Start(); server = CreateServer(endPoint); server.DescriptionChanged += ServerDescriptionChangedHandler; _servers.Add(server); } clusterDescription = clusterDescription.WithServerDescription(server.Description); server.Initialize(); stopwatch.Stop(); if (Listener != null) { Listener.ClusterAfterAddingServer(server.ServerId, stopwatch.Elapsed); } return(clusterDescription); }
private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args, List <IClusterableServer> newServers) { if (!args.NewServerDescription.Type.IsReplicaSetMember()) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type))); } if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost) { return(clusterDescription.WithServerDescription(args.NewServerDescription)); } if (_replicaSetName == null) { _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name; } if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName))); } clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription); clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription, newServers); if (args.NewServerDescription.CanonicalEndPoint != null && !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint)) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint.")); } if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary) { if (args.NewServerDescription.ReplicaSetConfig.Version != null) { bool isCurrentPrimaryStale = true; if (_maxElectionInfo != null) { isCurrentPrimaryStale = _maxElectionInfo.IsStale(args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId); var isReportedPrimaryStale = _maxElectionInfo.IsFresher( args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId); if (isReportedPrimaryStale && args.NewServerDescription.ElectionId != null) { // we only invalidate the "newly" reported stale primary if electionId was used. lock (_serversLock) { var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint)); server.Invalidate(); _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() => string.Format( @"Invalidating server: Setting ServerType to ""Unknown"" for {0} because it " + @"claimed to be the replica set primary for replica set ""{1}"" but sent a " + @"(setVersion, electionId) tuple of ({2}, {3}) that was less than than the " + @"largest tuple seen, (maxSetVersion, maxElectionId), of ({4}, {5}).", args.NewServerDescription.EndPoint, args.NewServerDescription.ReplicaSetConfig.Name, args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId, _maxElectionInfo.SetVersion, _maxElectionInfo.ElectionId))); return(clusterDescription.WithServerDescription( new ServerDescription(server.ServerId, server.EndPoint))); } } } if (isCurrentPrimaryStale) { if (_maxElectionInfo == null) { _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() => string.Format( @"Initializing (maxSetVersion, maxElectionId): Saving tuple " + @"(setVersion, electionId) of ({0}, {1}) as (maxSetVersion, maxElectionId) for " + @"replica set ""{2}"" because replica set primary {3} sent ({0}, {1}), the first " + @"(setVersion, electionId) tuple ever seen for replica set ""{4}"".", args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId, args.NewServerDescription.ReplicaSetConfig.Name, args.NewServerDescription.EndPoint, args.NewServerDescription.ReplicaSetConfig.Name))); } else { if (_maxElectionInfo.SetVersion < args.NewServerDescription.ReplicaSetConfig.Version.Value) { _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() => string.Format( @"Updating stale setVersion: Updating the current " + @"(maxSetVersion, maxElectionId) tuple from ({0}, {1}) to ({2}, {3}) for " + @"replica set ""{4}"" because replica set primary {5} sent ({6}, {7})—a larger " + @"(setVersion, electionId) tuple then the saved tuple, ({0}, {1}).", _maxElectionInfo.SetVersion, _maxElectionInfo.ElectionId, args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId, args.NewServerDescription.ReplicaSetConfig.Name, args.NewServerDescription.EndPoint, args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId))); } else // current primary is stale & setVersion is not stale ⇒ the electionId must be stale { _sdamInformationEventHandler?.Invoke(new SdamInformationEvent(() => string.Format( @"Updating stale electionId: Updating the current " + @"(maxSetVersion, maxElectionId) tuple from ({0}, {1}) to ({2}, {3}) for " + @"replica set ""{4}"" because replica set primary {5} sent ({6}, {7})—" + @"a larger (setVersion, electionId) tuple than the saved tuple, ({0}, {1}).", _maxElectionInfo.SetVersion, _maxElectionInfo.ElectionId, args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId, args.NewServerDescription.ReplicaSetConfig.Name, args.NewServerDescription.EndPoint, args.NewServerDescription.ReplicaSetConfig.Version, args.NewServerDescription.ElectionId))); } } _maxElectionInfo = new ElectionInfo( args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId); } } var currentPrimaryEndPoints = clusterDescription.Servers .Where(x => x.Type == ServerType.ReplicaSetPrimary) .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint)) .Select(x => x.EndPoint) .ToList(); if (currentPrimaryEndPoints.Count > 0) { lock (_serversLock) { var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint)); foreach (var currentPrimary in currentPrimaries) { // kick off the server to invalidate itself currentPrimary.Invalidate(); // set it to disconnected in the cluster clusterDescription = clusterDescription.WithServerDescription( new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint)); } } } } return(clusterDescription); }
private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args, List <IClusterableServer> newServers) { if (!args.NewServerDescription.Type.IsReplicaSetMember()) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type))); } if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost) { return(clusterDescription.WithServerDescription(args.NewServerDescription)); } if (_replicaSetName == null) { _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name; } if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName))); } clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription); clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription, newServers); if (args.NewServerDescription.CanonicalEndPoint != null && !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint)) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint.")); } if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary) { if (args.NewServerDescription.ReplicaSetConfig.Version != null) { bool isCurrentPrimaryStale = true; if (_maxElectionInfo != null) { isCurrentPrimaryStale = _maxElectionInfo.IsStale(args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId); var isReportedPrimaryStale = !isCurrentPrimaryStale; if (isReportedPrimaryStale && args.NewServerDescription.ElectionId != null) { // we only invalidate the "newly" reported stale primary if electionId was used. lock (_serversLock) { var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint)); server.Invalidate(); return(clusterDescription.WithServerDescription( new ServerDescription(server.ServerId, server.EndPoint))); } } } if (isCurrentPrimaryStale) { _maxElectionInfo = new ElectionInfo( args.NewServerDescription.ReplicaSetConfig.Version.Value, args.NewServerDescription.ElectionId); } } var currentPrimaryEndPoints = clusterDescription.Servers .Where(x => x.Type == ServerType.ReplicaSetPrimary) .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint)) .Select(x => x.EndPoint) .ToList(); if (currentPrimaryEndPoints.Count > 0) { lock (_serversLock) { var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint)); foreach (var currentPrimary in currentPrimaries) { // kick off the server to invalidate itself currentPrimary.Invalidate(); // set it to disconnected in the cluster clusterDescription = clusterDescription.WithServerDescription( new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint)); } } } } return(clusterDescription); }
private ClusterDescription ProcessReplicaSetChange(ClusterDescription clusterDescription, ServerDescriptionChangedEventArgs args) { if (!args.NewServerDescription.Type.IsReplicaSetMember()) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server is a {0}, not a replica set member.", args.NewServerDescription.Type))); } if (args.NewServerDescription.Type == ServerType.ReplicaSetGhost) { return(clusterDescription.WithServerDescription(args.NewServerDescription)); } if (_replicaSetName == null) { _replicaSetName = args.NewServerDescription.ReplicaSetConfig.Name; } if (_replicaSetName != args.NewServerDescription.ReplicaSetConfig.Name) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, string.Format("Server was a member of the '{0}' replica set, but should be '{1}'.", args.NewServerDescription.ReplicaSetConfig.Name, _replicaSetName))); } clusterDescription = clusterDescription.WithServerDescription(args.NewServerDescription); clusterDescription = EnsureServers(clusterDescription, args.NewServerDescription); if (args.NewServerDescription.CanonicalEndPoint != null && !EndPointHelper.Equals(args.NewServerDescription.CanonicalEndPoint, args.NewServerDescription.EndPoint)) { return(RemoveServer(clusterDescription, args.NewServerDescription.EndPoint, "CanonicalEndPoint is different than seed list EndPoint.")); } if (args.NewServerDescription.Type == ServerType.ReplicaSetPrimary) { if (args.NewServerDescription.ElectionId != null) { if (_maxElectionId != null && _maxElectionId.CompareTo(args.NewServerDescription.ElectionId) > 0) { // ignore this change because we've already seen this election id lock (_serversLock) { var server = _servers.SingleOrDefault(x => EndPointHelper.Equals(args.NewServerDescription.EndPoint, x.EndPoint)); server.Invalidate(); return(clusterDescription.WithServerDescription( new ServerDescription(server.ServerId, server.EndPoint))); } } _maxElectionId = args.NewServerDescription.ElectionId; } var currentPrimaryEndPoints = clusterDescription.Servers .Where(x => x.Type == ServerType.ReplicaSetPrimary) .Where(x => !EndPointHelper.Equals(x.EndPoint, args.NewServerDescription.EndPoint)) .Select(x => x.EndPoint) .ToList(); if (currentPrimaryEndPoints.Count > 0) { lock (_serversLock) { var currentPrimaries = _servers.Where(x => EndPointHelper.Contains(currentPrimaryEndPoints, x.EndPoint)); foreach (var currentPrimary in currentPrimaries) { // kick off the server to invalidate itself currentPrimary.Invalidate(); // set it to disconnected in the cluster clusterDescription = clusterDescription.WithServerDescription( new ServerDescription(currentPrimary.ServerId, currentPrimary.EndPoint)); } } } } return(clusterDescription); }