private void OnDescriptionChanged(ServerDescription oldDescription, ServerDescription newDescription) { var handler = DescriptionChanged; if (handler != null) { var args = new ServerDescriptionChangedEventArgs(oldDescription, newDescription); try { handler(this, args); } catch { } // ignore exceptions } }
protected override void InitializeSubClass() { // generate initial server description var newDescription = _baseDescription .With( type: ServerType.LoadBalanced, reasonChanged: "Initialized", state: ServerState.Connected); var oldDescription = Interlocked.CompareExchange(ref _currentDescription, value: newDescription, comparand: _currentDescription); var eventArgs = new ServerDescriptionChangedEventArgs(oldDescription, newDescription); // propagate event to upper levels, this will be called only once TriggerServerDescriptionChanged(this, eventArgs); }
protected override void InitializeSubClass() { // generate initial server description var newDescription = _baseDescription .With( type: ServerType.LoadBalanced, reasonChanged: "Initialized", state: ServerState.Connected); var oldDescription = Interlocked.CompareExchange(ref _currentDescription, value: newDescription, comparand: _currentDescription); var eventArgs = new ServerDescriptionChangedEventArgs(oldDescription, newDescription); // mark pool as ready, start the connection creation thread. // note that the pool can not be paused after it was marked as ready in LB mode. ConnectionPool.SetReady(); // propagate event to upper levels, this will be called only once TriggerServerDescriptionChanged(this, eventArgs); }
private void OnDescriptionChanged(ServerDescription newDescription) { var oldDescription = Interlocked.CompareExchange(ref _currentDescription, null, null); if (oldDescription.Equals(newDescription)) { return; } Interlocked.Exchange(ref _currentDescription, newDescription); var handler = DescriptionChanged; if (handler != null) { var args = new ServerDescriptionChangedEventArgs(oldDescription, newDescription); try { handler(this, args); } catch { } // ignore exceptions } }
private void OnDescriptionChanged(object sender, ServerDescriptionChangedEventArgs e) { if (e.NewServerDescription.HeartbeatException != null) { _connectionPool.Clear(); } if (_descriptionChangedEventHandler != null) { _descriptionChangedEventHandler(new ServerDescriptionChangedEvent(e.OldServerDescription, e.NewServerDescription)); } var handler = DescriptionChanged; if (handler != null) { try { handler(this, e); } catch { } // ignore exceptions } }
// private methods private void OnMonitorDescriptionChanged(object sender, ServerDescriptionChangedEventArgs e) { var currentDescription = _currentDescription; var heartbeatException = e.NewServerDescription.HeartbeatException; // The heartbeat commands are hello (or legacy hello) + buildInfo. These commands will throw a MongoCommandException on // {ok: 0}, but a reply (with a potential topologyVersion) will still have been received. // Not receiving a reply to the heartbeat commands implies a network error or a "HeartbeatFailed" type // exception (i.e. ServerDescription.WithHeartbeatException was called), in which case we should immediately // set the description to "Unknown"// (which is what e.NewServerDescription will be in such a case) var heartbeatReplyNotReceived = heartbeatException != null && !(heartbeatException is MongoCommandException); // We cannot use FresherThan(e.NewServerDescription.TopologyVersion, currentDescription.TopologyVersion) // because due to how TopologyVersions comparisons are defined, IsStalerThanOrEqualTo(x, y) does not imply // FresherThan(y, x) if (heartbeatReplyNotReceived || TopologyVersion.IsStalerThanOrEqualTo(currentDescription.TopologyVersion, e.NewServerDescription.TopologyVersion)) { SetDescription(e.NewServerDescription, forceClearConnectionPool: false); } }
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 void OnDescriptionChanged(ServerDescription newDescription) { var oldDescription = Interlocked.CompareExchange(ref _currentDescription, null, null); if (oldDescription.Equals(newDescription)) { return; } Interlocked.Exchange(ref _currentDescription, newDescription); var handler = DescriptionChanged; if (handler != null) { var args = new ServerDescriptionChangedEventArgs(oldDescription, newDescription); try { handler(this, args); } catch { } // ignore exceptions } }
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 void ServerDescriptionChanged(object sender, ServerDescriptionChangedEventArgs args) { var newServerDescription = args.NewServerDescription; var newClusterDescription = Description; 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); } } UpdateClusterDescription(newClusterDescription); }
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 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 void ProcessServerDescriptionChanged(ServerDescriptionChangedEventArgs args) { 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.ConnectionMode, newServerDescription.Type)) { if (newClusterDescription.Type == ClusterType.Unknown) { newClusterDescription = newClusterDescription.WithType(newServerDescription.Type.ToClusterType()); } switch (newClusterDescription.Type) { case ClusterType.ReplicaSet: newClusterDescription = ProcessReplicaSetChange(newClusterDescription, args); break; case ClusterType.Sharded: newClusterDescription = ProcessShardedChange(newClusterDescription, args); break; default: throw new MongoInternalException("Unexpected cluster type."); } } else { newClusterDescription = newClusterDescription.WithoutServerDescription(newServerDescription.EndPoint); } } UpdateClusterDescription(newClusterDescription); }
private void ServerDescriptionChangedHandler(object sender, ServerDescriptionChangedEventArgs args) { _serverDescriptionChangedQueue.Enqueue(args); }
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 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 => !x.EndPoint.Equals(args.NewServerDescription.EndPoint)) .Select(x => x.EndPoint) .ToList(); if (currentPrimaryEndPoints.Count > 0) { lock (_serversLock) { var currentPrimaries = _servers.Where(x => currentPrimaryEndPoints.Contains(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 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 (args.NewServerDescription.State == ServerState.Disconnected) { newClusterDescription = currentClusterDescription.WithServerDescription(args.NewServerDescription); } 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: newClusterDescription = ProcessStandaloneChange(currentClusterDescription, args); break; default: newClusterDescription = currentClusterDescription.WithServerDescription(newServerDescription); break; } } UpdateClusterDescription(newClusterDescription); }