private void ProcessServerDescriptionChanged(ServerDescriptionChangedEventArgs args) { var newServerDescription = args.NewServerDescription; var newClusterDescription = Description; if (!_servers.Any(x => EndPointHelper.Equals(x.EndPoint, newServerDescription.EndPoint))) { return; } var newServers = new List <IClusterableServer>(); if (newServerDescription.State == ServerState.Disconnected) { newClusterDescription = newClusterDescription.WithServerDescription(newServerDescription); } else { if (IsServerValidForCluster(newClusterDescription.Type, Settings.ConnectionMode, newServerDescription.Type)) { if (newClusterDescription.Type == ClusterType.Unknown) { newClusterDescription = newClusterDescription.WithType(newServerDescription.Type.ToClusterType()); } switch (newClusterDescription.Type) { case ClusterType.ReplicaSet: newClusterDescription = ProcessReplicaSetChange(newClusterDescription, args, newServers); break; case ClusterType.Sharded: newClusterDescription = ProcessShardedChange(newClusterDescription, args); break; default: throw new MongoInternalException("Unexpected cluster type."); } } else { newClusterDescription = newClusterDescription.WithoutServerDescription(newServerDescription.EndPoint); } } UpdateClusterDescription(newClusterDescription); foreach (var server in newServers) { server.Initialize(); } }
private void ProcessServerDescriptionChanged(ServerDescriptionChangedEventArgs args) { var currentClusterDescription = Description; var currentServerDescription = args.OldServerDescription; var newServerDescription = args.NewServerDescription; var currentServer = _servers.SingleOrDefault(x => x.EndPoint.Equals(newServerDescription.EndPoint)); if (currentServer == null) { return; } ClusterDescription newClusterDescription; if (newServerDescription.State == ServerState.Disconnected) { newClusterDescription = currentClusterDescription.WithServerDescription(args.NewServerDescription); } else if (newServerDescription.Type == ServerType.Standalone) { newClusterDescription = currentClusterDescription.WithoutServerDescription(args.NewServerDescription.EndPoint); } else { if (currentClusterDescription.Type == ClusterType.Unknown) { currentClusterDescription = currentClusterDescription.WithType(args.NewServerDescription.Type.ToClusterType()); } switch (currentClusterDescription.Type) { case ClusterType.ReplicaSet: newClusterDescription = ProcessReplicaSetChange(currentClusterDescription, args); break; case ClusterType.Sharded: newClusterDescription = ProcessShardedChange(currentClusterDescription, args); break; case ClusterType.Standalone: throw new MongoInternalException("MultiServerCluster does not support a standalone state."); default: newClusterDescription = currentClusterDescription.WithServerDescription(newServerDescription); break; } } UpdateClusterDescription(newClusterDescription); }
private void ServerDescriptionChanged(object sender, ServerDescriptionChangedEventArgs args) { var newServerDescription = args.NewServerDescription; var newClusterDescription = Description; if (_replicaSetName != null) { var replicaSetConfig = newServerDescription.ReplicaSetConfig; if (replicaSetConfig == null || replicaSetConfig.Name != _replicaSetName) { // if the replica set name does not match then the ServerType in the ServerDescription MUST be replaced with Unknown newServerDescription = newServerDescription.With(type: ServerType.Unknown); } } if (newServerDescription.State == ServerState.Disconnected) { newClusterDescription = newClusterDescription.WithServerDescription(newServerDescription); } else { if (IsServerValidForCluster(newClusterDescription.Type, Settings.ConnectionMode, newServerDescription.Type)) { if (newClusterDescription.Type == ClusterType.Unknown) { newClusterDescription = newClusterDescription.WithType(newServerDescription.Type.ToClusterType()); } newClusterDescription = newClusterDescription.WithServerDescription(newServerDescription); } else { newClusterDescription = newClusterDescription.WithoutServerDescription(newServerDescription.EndPoint); } } var shouldClusterDescriptionChangedEventBePublished = !args.OldServerDescription.SdamEquals(args.NewServerDescription); UpdateClusterDescription(newClusterDescription, shouldClusterDescriptionChangedEventBePublished); }
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 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 void ServerDescriptionChangedHandler(object sender, ServerDescriptionChangedEventArgs args) { _serverDescriptionChangedQueue.Enqueue(args); }
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 void ProcessServerDescriptionChanged(ServerDescriptionChangedEventArgs args) { var newServers = new List <IClusterableServer>(); lock (_updateClusterDescriptionLock) { var newServerDescription = args.NewServerDescription; var newClusterDescription = Description; if (!_servers.Any(x => EndPointHelper.Equals(x.EndPoint, newServerDescription.EndPoint))) { return; } if (newServerDescription.State == ServerState.Disconnected) { newClusterDescription = newClusterDescription.WithServerDescription(newServerDescription); } else { if (IsServerValidForCluster(newClusterDescription.Type, Settings, newServerDescription.Type)) { if (newClusterDescription.Type == ClusterType.Unknown) { if (newServerDescription.Type != ServerType.ReplicaSetGhost) { // Unknown cluster description with ServerType.ReplicaSetGhost should be untouched newClusterDescription = newClusterDescription.WithType(newServerDescription.Type.ToClusterType()); } } switch (newClusterDescription.Type) { case ClusterType.Standalone: newClusterDescription = ProcessStandaloneChange(newClusterDescription, args); break; case ClusterType.ReplicaSet: case ClusterType.Unknown when newServerDescription.Type == ServerType.ReplicaSetGhost: // update serverDescription in clusterDescription newClusterDescription = ProcessReplicaSetChange(newClusterDescription, args, newServers); break; case ClusterType.Sharded: newClusterDescription = ProcessShardedChange(newClusterDescription, args); break; default: throw new MongoInternalException("Unexpected cluster type."); } } else { var reason = $"The server {newServerDescription.EndPoint} with type {newServerDescription.Type} is not valid for cluster type {newClusterDescription.Type}."; newClusterDescription = RemoveServer(newClusterDescription, newServerDescription.EndPoint, reason); } } var shouldClusterDescriptionChangedEventBePublished = !args.OldServerDescription.SdamEquals(args.NewServerDescription); UpdateClusterDescription(newClusterDescription, shouldClusterDescriptionChangedEventBePublished); } foreach (var server in newServers) { server.Initialize(); } }
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 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); }
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)); } }