private void ApplyResponse(BsonArray response) { if (response.Count != 2) { throw new FormatException($"Invalid response count: {response.Count}."); } var address = response[0].AsString; var isMasterDocument = response[1].AsBsonDocument; VerifyFields(isMasterDocument, "arbiterOnly", "arbiters", "electionId", "hidden", "hosts", "ismaster", "isreplicaset", "logicalSessionTimeoutMinutes", "maxWireVersion", "me", "minWireVersion", "msg", "ok", "passive", "passives", "primary", "secondary", "setName", "setVersion"); var endPoint = EndPointHelper.Parse(address); var isMasterResult = new IsMasterResult(isMasterDocument); var currentServerDescription = _serverFactory.GetServerDescription(endPoint); var newServerDescription = currentServerDescription.With( canonicalEndPoint: isMasterResult.Me, electionId: isMasterResult.ElectionId, logicalSessionTimeout: isMasterResult.LogicalSessionTimeout, replicaSetConfig: isMasterResult.GetReplicaSetConfig(), state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: isMasterResult.ServerType, wireVersionRange: new Range <int>(isMasterResult.MinWireVersion, isMasterResult.MaxWireVersion)); var currentClusterDescription = _cluster.Description; _serverFactory.PublishDescription(newServerDescription); SpinWait.SpinUntil(() => !object.ReferenceEquals(_cluster.Description, currentClusterDescription), 100); // sometimes returns false and that's OK }
public void GetReplicaSetConfig_should_return_correct_info_when_the_server_is_a_replica_set() { var doc = new BsonDocument { { "ok", 1 }, { "setName", "funny" }, { "primary", "localhost:1000" }, { "hosts", new BsonArray(new [] { "localhost:1000", "localhost:1001" })}, { "passives", new BsonArray(new [] { "localhost:1002"}) }, { "arbiters", new BsonArray(new [] { "localhost:1003"}) }, { "version", 20 } }; var subject = new IsMasterResult(doc); var config = subject.GetReplicaSetConfig(); config.Name.Should().Be("funny"); config.Primary.Should().Be(new DnsEndPoint("localhost", 1000)); config.Members.Should().BeEquivalentTo( new DnsEndPoint("localhost", 1000), new DnsEndPoint("localhost", 1001), new DnsEndPoint("localhost", 1002), new DnsEndPoint("localhost", 1003)); config.Version.Should().Be(20); }
private void ApplyResponse(BsonArray response) { if (response.Count != 2) { throw new FormatException($"Invalid response count: {response.Count}."); } var address = response[0].AsString; var isMasterDocument = response[1].AsBsonDocument; JsonDrivenHelper.EnsureAllFieldsAreValid(isMasterDocument, "hosts", "isWritablePrimary", OppressiveLanguageConstants.LegacyHelloResponseIsWritablePrimaryFieldName, "helloOk", "maxWireVersion", "minWireVersion", "ok", "primary", "secondary", "setName", "setVersion"); var endPoint = EndPointHelper.Parse(address); var isMasterResult = new IsMasterResult(isMasterDocument); var currentServerDescription = _serverFactory.GetServerDescription(endPoint); var newServerDescription = currentServerDescription.With( canonicalEndPoint: isMasterResult.Me, electionId: isMasterResult.ElectionId, replicaSetConfig: isMasterResult.GetReplicaSetConfig(), state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: isMasterResult.ServerType, wireVersionRange: new Range <int>(isMasterResult.MinWireVersion, isMasterResult.MaxWireVersion)); var currentClusterDescription = _cluster.Description; _serverFactory.PublishDescription(newServerDescription); SpinWait.SpinUntil(() => !object.ReferenceEquals(_cluster.Description, currentClusterDescription), 100); // sometimes returns false and that's OK }
private void ApplyResponse(BsonValue response) { var server = (string)response[0]; var endPoint = EndPointHelper.Parse(server); var isMasterResult = new IsMasterResult((BsonDocument)response[1]); var currentDescription = _serverFactory.GetServerDescription(endPoint); var description = currentDescription.With( state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: isMasterResult.ServerType, replicaSetConfig: isMasterResult.GetReplicaSetConfig()); _serverFactory.PublishDescription(description); }
private void ApplyResponse(BsonValue response) { var server = (string)response[0]; var endPoint = EndPointHelper.Parse(server); var isMasterResult = new IsMasterResult((BsonDocument)response[1]); var currentDescription = _serverFactory.GetServerDescription(endPoint); var description = currentDescription.With( state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: isMasterResult.ServerType, canonicalEndPoint: isMasterResult.Me, electionId: isMasterResult.ElectionId, replicaSetConfig: isMasterResult.GetReplicaSetConfig()); _serverFactory.PublishDescription(description); }
private void ApplyResponse(BsonValue response) { var server = (string)response[0]; var endPoint = EndPointHelper.Parse(server); var isMasterResult = new IsMasterResult((BsonDocument)response[1]); var currentServerDescription = _serverFactory.GetServerDescription(endPoint); var newServerDescription = currentServerDescription.With( state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: isMasterResult.ServerType, canonicalEndPoint: isMasterResult.Me, electionId: isMasterResult.ElectionId, replicaSetConfig: isMasterResult.GetReplicaSetConfig()); var currentClusterDescription = _cluster.Description; _serverFactory.PublishDescription(newServerDescription); SpinWait.SpinUntil(() => !object.ReferenceEquals(_cluster.Description, currentClusterDescription), 100); // sometimes returns false and that's OK }
private async Task HeartbeatAsync(CancellationToken cancellationToken) { CommandWireProtocol <BsonDocument> isMasterProtocol = null; bool processAnother = true; while (processAnother && !cancellationToken.IsCancellationRequested) { IsMasterResult heartbeatIsMasterResult = null; Exception heartbeatException = null; var previousDescription = _currentDescription; try { IConnection connection; lock (_lock) { connection = _connection; } if (connection == null) { var initializedConnection = await InitializeConnectionAsync(cancellationToken).ConfigureAwait(false); lock (_lock) { if (_state.Value == State.Disposed) { try { initializedConnection.Dispose(); } catch { } throw new OperationCanceledException("The ServerMonitor has been disposed."); } _connection = initializedConnection; _handshakeBuildInfoResult = _connection.Description.BuildInfoResult; heartbeatIsMasterResult = _connection.Description.IsMasterResult; } } else { isMasterProtocol = isMasterProtocol ?? InitializeIsMasterProtocol(connection); heartbeatIsMasterResult = await GetIsMasterResultAsync(connection, isMasterProtocol, cancellationToken).ConfigureAwait(false); } } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { return; } catch (Exception ex) { IConnection toDispose = null; lock (_lock) { isMasterProtocol = null; heartbeatException = ex; _roundTripTimeMonitor.Reset(); toDispose = _connection; _connection = null; } toDispose?.Dispose(); } lock (_lock) { if (cancellationToken.IsCancellationRequested) { return; } } ServerDescription newDescription; if (heartbeatIsMasterResult != null) { if (_handshakeBuildInfoResult == null) { // we can be here only if there is a bug in the driver throw new ArgumentNullException("BuildInfo has been lost."); } var averageRoundTripTime = _roundTripTimeMonitor.Average; var averageRoundTripTimeRounded = TimeSpan.FromMilliseconds(Math.Round(averageRoundTripTime.TotalMilliseconds)); newDescription = _baseDescription.With( averageRoundTripTime: averageRoundTripTimeRounded, canonicalEndPoint: heartbeatIsMasterResult.Me, electionId: heartbeatIsMasterResult.ElectionId, lastWriteTimestamp: heartbeatIsMasterResult.LastWriteTimestamp, logicalSessionTimeout: heartbeatIsMasterResult.LogicalSessionTimeout, maxBatchCount: heartbeatIsMasterResult.MaxBatchCount, maxDocumentSize: heartbeatIsMasterResult.MaxDocumentSize, maxMessageSize: heartbeatIsMasterResult.MaxMessageSize, replicaSetConfig: heartbeatIsMasterResult.GetReplicaSetConfig(), state: ServerState.Connected, tags: heartbeatIsMasterResult.Tags, topologyVersion: heartbeatIsMasterResult.TopologyVersion, type: heartbeatIsMasterResult.ServerType, version: _handshakeBuildInfoResult.ServerVersion, wireVersionRange: new Range <int>(heartbeatIsMasterResult.MinWireVersion, heartbeatIsMasterResult.MaxWireVersion)); } else { newDescription = _baseDescription.With(lastUpdateTimestamp: DateTime.UtcNow); } if (heartbeatException != null) { var topologyVersion = default(Optional <TopologyVersion>); if (heartbeatException is MongoCommandException heartbeatCommandException) { topologyVersion = TopologyVersion.FromMongoCommandException(heartbeatCommandException); } newDescription = newDescription.With(heartbeatException: heartbeatException, topologyVersion: topologyVersion); } newDescription = newDescription.With(reasonChanged: "Heartbeat", lastHeartbeatTimestamp: DateTime.UtcNow); lock (_lock) { cancellationToken.ThrowIfCancellationRequested(); SetDescription(newDescription); } processAnother = // serverSupportsStreaming (newDescription.Type != ServerType.Unknown && heartbeatIsMasterResult != null && heartbeatIsMasterResult.TopologyVersion != null) || // connectionIsStreaming (isMasterProtocol != null && isMasterProtocol.MoreToCome) || // transitionedWithNetworkError (IsNetworkError(heartbeatException) && previousDescription.Type != ServerType.Unknown); } bool IsNetworkError(Exception ex) { return(ex is MongoConnectionException mongoConnectionException && mongoConnectionException.IsNetworkException); } }