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(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 }
// methods /// <inheritdoc/> public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); // If we don't have SaslSupportedMechs as part of the response, that means we didn't piggyback the initial // hello or legacy hello request and should query the server (provided that the server >= 4.0), merging results into // a new ConnectionDescription if (!description.IsMasterResult.HasSaslSupportedMechs && Feature.ScramSha256Authentication.IsSupported(description.ServerVersion)) { var command = CustomizeInitialIsMasterCommand(HelloHelper.CreateCommand()); var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi); var helloResult = HelloHelper.GetResult(connection, helloProtocol, cancellationToken); var mergedHelloResult = new IsMasterResult(description.IsMasterResult.Wrapped.Merge(helloResult.Wrapped)); description = new ConnectionDescription( description.ConnectionId, mergedHelloResult, description.BuildInfoResult); } var authenticator = GetOrCreateAuthenticator(connection, description); authenticator.Authenticate(connection, description, cancellationToken); }
/// <inheritdoc/> public async Task AuthenticateAsync(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); // If we don't have SaslSupportedMechs as part of the response, that means we didn't piggyback the initial // isMaster request and should query the server (provided that the server >= 4.0), merging results into // a new ConnectionDescription if (!description.IsMasterResult.HasSaslSupportedMechs && Feature.ScramSha256Authentication.IsSupported(description.ServerVersion)) { var command = CustomizeInitialIsMasterCommand(IsMasterHelper.CreateCommand()); var isMasterProtocol = IsMasterHelper.CreateProtocol(command); var isMasterResult = await IsMasterHelper.GetResultAsync(connection, isMasterProtocol, cancellationToken).ConfigureAwait(false); var mergedIsMasterResult = new IsMasterResult(description.IsMasterResult.Wrapped.Merge(isMasterResult.Wrapped)); description = new ConnectionDescription( description.ConnectionId, mergedIsMasterResult, description.BuildInfoResult); } var authenticator = GetOrCreateAuthenticator(connection, description); await authenticator.AuthenticateAsync(connection, description, cancellationToken).ConfigureAwait(false); }
public void Equals_should_be_true_when_both_have_the_same_result() { var subject1 = new IsMasterResult(new BsonDocument("x", 1)); var subject2 = new IsMasterResult(new BsonDocument("x", 1)); subject1.Equals(subject2).Should().BeTrue(); }
public async Task<ConnectionDescription> InitializeConnectionAsync(IConnection connection, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); var isMasterProtocol = CreateIsMasterProtocol(); var isMasterResult = new IsMasterResult(await isMasterProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false)); var buildInfoProtocol = CreateBuildInfoProtocol(); var buildInfoResult = new BuildInfoResult(await buildInfoProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false)); var description = new ConnectionDescription(connection.ConnectionId, isMasterResult, buildInfoResult); await AuthenticationHelper.AuthenticateAsync(connection, description, cancellationToken).ConfigureAwait(false); try { var getLastErrorProtocol = CreateGetLastErrorProtocol(); var getLastErrorResult = await getLastErrorProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); description = UpdateConnectionIdWithServerValue(description, getLastErrorResult); } catch { // if we couldn't get the server's connection id, so be it. } return description; }
public void Equals_should_be_false_when_both_have_different_results() { var subject1 = new IsMasterResult(new BsonDocument("x", 1)); var subject2 = new IsMasterResult(new BsonDocument("x", 2)); subject1.Equals(subject2).Should().BeFalse(); }
public void ElectionId_should_parse_document_correctly(string json, string expectedObjectId) { var subject = new IsMasterResult(BsonDocument.Parse(json)); var expected = expectedObjectId == null ? (ElectionId)null : new ElectionId(ObjectId.Parse(expectedObjectId)); subject.ElectionId.Should().Be(expected); }
public void Wrapped_should_return_the_document_passed_in_the_constructor() { var doc = new BsonDocument(); var subject = new IsMasterResult(doc); subject.Wrapped.Should().BeSameAs(doc); }
public void LastWriteTimestamp_should_parse_document_correctly(string json, int? expectedYear) { var subject = new IsMasterResult(BsonDocument.Parse(json)); var result = subject.LastWriteTimestamp; var expectedResult = expectedYear.HasValue ? new DateTime(expectedYear.Value, 1, 1, 0, 0, 0, DateTimeKind.Utc) : (DateTime?)null; result.Should().Be(expectedResult); }
public void TestMaxWriteBatchSizeWhenNotServerSupplied() { var document = new BsonDocument { { "ok", 1 } }; var result = new IsMasterResult(document); Assert.AreEqual(1000, result.MaxWriteBatchSize); }
private async Task <HeartbeatInfo> GetHeartbeatInfoAsync(IConnection connection, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_heartbeatStartedEventHandler != null) { _heartbeatStartedEventHandler(new ServerHeartbeatStartedEvent(connection.ConnectionId)); } try { var isMasterCommand = new CommandWireProtocol <BsonDocument>( DatabaseNamespace.Admin, new BsonDocument("isMaster", 1), true, BsonDocumentSerializer.Instance, null); var stopwatch = Stopwatch.StartNew(); var isMasterResultDocument = await isMasterCommand.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); var isMasterResult = new IsMasterResult(isMasterResultDocument); var buildInfoCommand = new CommandWireProtocol <BsonDocument>( DatabaseNamespace.Admin, new BsonDocument("buildInfo", 1), true, BsonDocumentSerializer.Instance, null); var buildInfoResultRocument = await buildInfoCommand.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); var buildInfoResult = new BuildInfoResult(buildInfoResultRocument); if (_heartbeatSucceededEventHandler != null) { _heartbeatSucceededEventHandler(new ServerHeartbeatSucceededEvent(connection.ConnectionId, stopwatch.Elapsed)); } return(new HeartbeatInfo { RoundTripTime = stopwatch.Elapsed, IsMasterResult = isMasterResult, BuildInfoResult = buildInfoResult }); } catch (Exception ex) { if (_heartbeatFailedEventHandler != null) { _heartbeatFailedEventHandler(new ServerHeartbeatFailedEvent(connection.ConnectionId, ex)); } throw; } }
private async Task <HeartbeatInfo> GetHeartbeatInfoAsync(IConnection connection, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_listener != null) { _listener.ServerBeforeHeartbeating(connection.ConnectionId); } try { var slidingTimeout = new SlidingTimeout(_settings.HeartbeatTimeout); var isMasterCommand = new CommandWireProtocol( DatabaseNamespace.Admin, new BsonDocument("isMaster", 1), true, null); var stopwatch = Stopwatch.StartNew(); var isMasterResultDocument = await isMasterCommand.ExecuteAsync(connection, slidingTimeout, cancellationToken); stopwatch.Stop(); var isMasterResult = new IsMasterResult(isMasterResultDocument); var buildInfoCommand = new CommandWireProtocol( DatabaseNamespace.Admin, new BsonDocument("buildInfo", 1), true, null); var buildInfoResultRocument = await buildInfoCommand.ExecuteAsync(connection, slidingTimeout, cancellationToken); var buildInfoResult = new BuildInfoResult(buildInfoResultRocument); if (_listener != null) { _listener.ServerAfterHeartbeating(connection.ConnectionId, stopwatch.Elapsed); } return(new HeartbeatInfo { RoundTripTime = stopwatch.Elapsed, IsMasterResult = isMasterResult, BuildInfoResult = buildInfoResult }); } catch (Exception ex) { if (_listener != null) { _listener.ServerErrorHeartbeating(connection.ConnectionId, ex); } throw; } }
public void TestMaxMessageLengthWhenNotServerSuppliedUsesMaxBsonObjectSizeWhenLargerThanMongoDefaults() { var document = new BsonDocument { { "ok", 1 }, { "maxBsonObjectSize", MongoDefaults.MaxMessageLength } }; var result = new IsMasterResult(document); Assert.AreEqual(MongoDefaults.MaxMessageLength + 1024, result.MaxMessageLength); }
public void TestMaxMessageLengthWhenServerSupplied() { var document = new BsonDocument { { "ok", 1 }, { "maxMessageSizeBytes", 1000 }, { "maxBsonObjectSize", 1000 } }; var result = new IsMasterResult(document); Assert.AreEqual(1000, result.MaxMessageLength); }
public async Task<ConnectionDescription> InitializeConnectionAsync(IConnection connection, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); var isMasterCommand = new BsonDocument("isMaster", 1); var isMasterProtocol = new CommandWireProtocol<BsonDocument>( DatabaseNamespace.Admin, isMasterCommand, true, BsonDocumentSerializer.Instance, null); var isMasterResult = new IsMasterResult(await isMasterProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false)); var buildInfoCommand = new BsonDocument("buildInfo", 1); var buildInfoProtocol = new CommandWireProtocol<BsonDocument>( DatabaseNamespace.Admin, buildInfoCommand, true, BsonDocumentSerializer.Instance, null); var buildInfoResult = new BuildInfoResult(await buildInfoProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false)); var connectionId = connection.ConnectionId; var description = new ConnectionDescription(connectionId, isMasterResult, buildInfoResult); await AuthenticationHelper.AuthenticateAsync(connection, description, cancellationToken).ConfigureAwait(false); try { var getLastErrorCommand = new BsonDocument("getLastError", 1); var getLastErrorProtocol = new CommandWireProtocol<BsonDocument>( DatabaseNamespace.Admin, getLastErrorCommand, true, BsonDocumentSerializer.Instance, null); var getLastErrorResult = await getLastErrorProtocol.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); BsonValue connectionIdBsonValue; if (getLastErrorResult.TryGetValue("connectionId", out connectionIdBsonValue)) { connectionId = connectionId.WithServerValue(connectionIdBsonValue.ToInt32()); description = description.WithConnectionId(connectionId); } } catch { // if we couldn't get the server's connection id, so be it. } return 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, replicaSetConfig: isMasterResult.GetReplicaSetConfig()); _serverFactory.PublishDescription(description); }
// private methods private ConnectionDescription CreateConnectionDescription(SemanticVersion serverVersion) { var clusterId = new ClusterId(1); var serverId = new ServerId(clusterId, new DnsEndPoint("localhost", 27017)); var connectionId = new ConnectionId(serverId, 1); var isMasterResult = new IsMasterResult(new BsonDocument()); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", serverVersion.ToString() } }); return(new ConnectionDescription(connectionId, isMasterResult, buildInfoResult)); }
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 ConnectionDescription CreateConnectionDescription(bool areRetryableWritesSupported) { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var isMasterResultDocument = BsonDocument.Parse("{ ok : 1 }"); if (areRetryableWritesSupported) { isMasterResultDocument["logicalSessionTimeoutMinutes"] = 1; isMasterResultDocument["msg"] = "isdbgrid"; // mongos } var isMasterResult = new IsMasterResult(isMasterResultDocument); var buildInfoResult = new BuildInfoResult(BsonDocument.Parse("{ ok : 1, version : '4.2.0' }")); var connectionDescription = new ConnectionDescription(connectionId, isMasterResult, buildInfoResult); return(connectionDescription); }
// private methods private ConnectionDescription CreateConnectionDescriptionSupportingSession() { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var isMasterDocument = new BsonDocument { { "logicalSessionTimeoutMinutes", 30 } }; var isMasterResult = new IsMasterResult(isMasterDocument); var buildInfoDocument = new BsonDocument { { "version", "3.6.0" } }; var buildInfoResult = new BuildInfoResult(buildInfoDocument); return(new ConnectionDescription(connectionId, isMasterResult, buildInfoResult)); }
public void Equals_should_return_correct_results() { var connectionId1 = new ConnectionId(new ServerId(new ClusterId(), new DnsEndPoint("localhost", 27018)), 10); var connectionId2 = new ConnectionId(new ServerId(new ClusterId(), new DnsEndPoint("localhost", 27018)), 10); var isMasterResult1 = new IsMasterResult(new BsonDocument("x", 1)); var isMasterResult2 = new IsMasterResult(new BsonDocument("x", 2)); var buildInfoResult1 = new BuildInfoResult(new BsonDocument("version", "2.6.3")); var buildInfoResult2 = new BuildInfoResult(new BsonDocument("version", "2.4.10")); var subject1 = new ConnectionDescription(connectionId1, isMasterResult1, buildInfoResult1); var subject2 = new ConnectionDescription(connectionId1, isMasterResult1, buildInfoResult1); var subject3 = new ConnectionDescription(connectionId1, isMasterResult1, buildInfoResult2); var subject4 = new ConnectionDescription(connectionId1, isMasterResult2, buildInfoResult1); var subject5 = new ConnectionDescription(connectionId2, isMasterResult1, buildInfoResult1); subject1.Equals(subject2).Should().BeTrue(); subject1.Equals(subject3).Should().BeFalse(); subject1.Equals(subject4).Should().BeFalse(); subject1.Equals(subject5).Should().BeFalse(); }
public void PublishDescription(ServerDescription description) { ServerTuple result; if (!_servers.TryGetValue(description.EndPoint, out result)) { throw new InvalidOperationException("Server does not exist."); } var oldDescription = result.Server.Description; if (result.Monitor == null) { var mockServer = Mock.Get(result.Server); mockServer.SetupGet(s => s.Description).Returns(description); mockServer.Raise(s => s.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(oldDescription, description)); } else { if (description.Version != null || description.WireVersionRange != null) { var version = description.Version?.ToString() ?? WireVersionHelper.MapWireVersionToServerVersion(description.WireVersionRange.Max); var server = (Server)result.Server; var isMasterResult = new IsMasterResult(new BsonDocument { { "compressors", new BsonArray() } }); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", version } }); var mockConnection = Mock.Get(server._connectionPool().AcquireConnection(CancellationToken.None)); mockConnection.SetupGet(c => c.Description) .Returns(new ConnectionDescription(new ConnectionId(description.ServerId, 0), isMasterResult, buildInfoResult)); } var mockMonitor = Mock.Get(result.Monitor); mockMonitor.SetupGet(m => m.Description).Returns(description); mockMonitor.Raise(m => m.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(oldDescription, description)); } }
private ConnectionDescription CreateConnectionDescription(bool withLogicalSessionTimeout, bool?serviceId = null) { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var isMasterResultDocument = BsonDocument.Parse("{ ok : 1 }"); if (withLogicalSessionTimeout) { isMasterResultDocument["logicalSessionTimeoutMinutes"] = 1; isMasterResultDocument["msg"] = "isdbgrid"; // mongos } if (serviceId.HasValue) { isMasterResultDocument["serviceId"] = ObjectId.Empty; // load balancing mode } var isMasterResult = new IsMasterResult(isMasterResultDocument); var buildInfoResult = new BuildInfoResult(BsonDocument.Parse("{ ok : 1, version : '4.2.0' }")); var connectionDescription = new ConnectionDescription(connectionId, isMasterResult, buildInfoResult); return(connectionDescription); }
public async Task<ConnectionDescription> InitializeConnectionAsync(IConnection connection, ConnectionId connectionId, TimeSpan timeout, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, "connection"); Ensure.IsNotNull(connectionId, "connectionId"); Ensure.IsInfiniteOrGreaterThanOrEqualToZero(timeout, "timeout"); var slidingTimeout = new SlidingTimeout(timeout); var isMasterCommand = new BsonDocument("isMaster", 1); var isMasterProtocol = new CommandWireProtocol("admin", isMasterCommand, true); var isMasterResult = new IsMasterResult(await isMasterProtocol.ExecuteAsync(connection, slidingTimeout, cancellationToken)); // authentication is currently broken on arbiters if (!isMasterResult.IsArbiter) { foreach (var authenticator in connection.Settings.Authenticators) { await authenticator.AuthenticateAsync(connection, slidingTimeout, cancellationToken); } } var buildInfoCommand = new BsonDocument("buildInfo", 1); var buildInfoProtocol = new CommandWireProtocol("admin", buildInfoCommand, true); var buildInfoResult = new BuildInfoResult(await buildInfoProtocol.ExecuteAsync(connection, slidingTimeout, cancellationToken)); var getLastErrorCommand = new BsonDocument("getLastError", 1); var getLastErrorProtocol = new CommandWireProtocol("admin", getLastErrorCommand, true); var getLastErrorResult = await getLastErrorProtocol.ExecuteAsync(connection, slidingTimeout, cancellationToken); BsonValue connectionIdBsonValue; if (getLastErrorResult.TryGetValue("connectionId", out connectionIdBsonValue)) { connectionId = connectionId.WithServerValue(connectionIdBsonValue.ToInt32()); } return new ConnectionDescription(connectionId, isMasterResult, buildInfoResult); }
private async Task<HeartbeatInfo> GetHeartbeatInfoAsync(IConnection connection, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_heartbeatStartedEventHandler != null) { _heartbeatStartedEventHandler(new ServerHeartbeatStartedEvent(connection.ConnectionId)); } try { var isMasterCommand = new CommandWireProtocol<BsonDocument>( DatabaseNamespace.Admin, new BsonDocument("isMaster", 1), true, BsonDocumentSerializer.Instance, null); var stopwatch = Stopwatch.StartNew(); var isMasterResultDocument = await isMasterCommand.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); var isMasterResult = new IsMasterResult(isMasterResultDocument); var buildInfoCommand = new CommandWireProtocol<BsonDocument>( DatabaseNamespace.Admin, new BsonDocument("buildInfo", 1), true, BsonDocumentSerializer.Instance, null); var buildInfoResultRocument = await buildInfoCommand.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); var buildInfoResult = new BuildInfoResult(buildInfoResultRocument); if (_heartbeatSucceededEventHandler != null) { _heartbeatSucceededEventHandler(new ServerHeartbeatSucceededEvent(connection.ConnectionId, stopwatch.Elapsed)); } return new HeartbeatInfo { RoundTripTime = stopwatch.Elapsed, IsMasterResult = isMasterResult, BuildInfoResult = buildInfoResult }; } catch (Exception ex) { if (_heartbeatFailedEventHandler != null) { _heartbeatFailedEventHandler(new ServerHeartbeatFailedEvent(connection.ConnectionId, ex)); } throw; } }
public void MaxDocumentSize_should_parse_document_correctly(string json, int expected) { var subject = new IsMasterResult(BsonDocument.Parse(json)); subject.MaxDocumentSize.Should().Be(expected); }
// private methods private ConnectionDescription CreateConnectionDescription(SemanticVersion serverVersion) { var clusterId = new ClusterId(1); var serverId = new ServerId(clusterId, new DnsEndPoint("localhost", 27017)); var connectionId = new ConnectionId(serverId, 1); var isMasterResult = new IsMasterResult(new BsonDocument()); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", serverVersion.ToString() } }); return new ConnectionDescription(connectionId, isMasterResult, buildInfoResult); }
public void WithConnectionId_should_return_new_instance_even_when_only_the_serverValue_differs() { var clusterId = new ClusterId(); var serverId = new ServerId(clusterId, new DnsEndPoint("localhost", 1)); var connectionId1 = new ConnectionId(serverId, 1); var connectionId2 = new ConnectionId(serverId, 1).WithServerValue(2); var isMasterResult = new IsMasterResult(new BsonDocument()); var buildInfoResult = new BuildInfoResult(new BsonDocument("version", "2.6.0")); var subject = new ConnectionDescription(connectionId1, isMasterResult, buildInfoResult); var result = subject.WithConnectionId(connectionId2); result.Should().NotBeSameAs(subject); result.ConnectionId.Should().BeSameAs(connectionId2); }
public void Tags_should_parse_document_correctly() { var subject = new IsMasterResult(BsonDocument.Parse("{ tags: { a: \"one\", b: \"two\" } }")); var expected = new TagSet(new[] { new Tag("a", "one"), new Tag("b", "two") }); subject.Tags.Should().Be(expected); }
public void Tags_should_be_null_when_no_tags_exist() { var subject = new IsMasterResult(new BsonDocument()); subject.Tags.Should().BeNull(); }
public void ServerType_should_parse_document_correctly(string json, ServerType expected) { var subject = new IsMasterResult(BsonDocument.Parse(json)); subject.ServerType.Should().Be(expected); }
public void Me_should_parse_document_correctly(string json, string expectedEndPoint) { var endPoint = expectedEndPoint == null ? (EndPoint)null : EndPointHelper.Parse(expectedEndPoint); var subject = new IsMasterResult(BsonDocument.Parse(json)); subject.Me.Should().Be(endPoint); }
public void MinWireVersion_should_parse_document_correctly(string json, int expected) { var subject = new IsMasterResult(BsonDocument.Parse(json)); subject.MinWireVersion.Should().Be(expected); }
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); } }
private void ApplyApplicationError(BsonDocument applicationError) { var expectedKeys = new[] { "address", "generation", // optional "maxWireVersion", "when", "type", "response" // optional }; JsonDrivenHelper.EnsureAllFieldsAreValid(applicationError, expectedKeys); var address = applicationError["address"].AsString; var endPoint = EndPointHelper.Parse(address); var server = (Server)_serverFactory.GetServer(endPoint); var connectionId = new ConnectionId(server.ServerId); var type = applicationError["type"].AsString; var maxWireVersion = applicationError["maxWireVersion"].AsInt32; Exception simulatedException = null; switch (type) { case "command": var response = applicationError["response"].AsBsonDocument; var command = new BsonDocument("Link", "start!"); simulatedException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, command, response, "errmsg"); Ensure.IsNotNull(simulatedException, nameof(simulatedException)); break; case "network": { var innerException = CoreExceptionHelper.CreateException("IOExceptionWithNetworkUnreachableSocketException"); simulatedException = new MongoConnectionException(connectionId, "Ignorance, yet knowledge.", innerException); break; } case "timeout": { var innerException = CoreExceptionHelper.CreateException("IOExceptionWithTimedOutSocketException"); simulatedException = new MongoConnectionException(connectionId, "Chaos, yet harmony.", innerException); break; } default: throw new ArgumentException($"Unsupported value of {type} for type"); } var mockConnection = new Mock <IConnectionHandle>(); var isMasterResult = new IsMasterResult(new BsonDocument { { "compressors", new BsonArray() } }); var serverVersion = WireVersionHelper.MapWireVersionToServerVersion(maxWireVersion); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", serverVersion } }); mockConnection.SetupGet(c => c.Description) .Returns(new ConnectionDescription(connectionId, isMasterResult, buildInfoResult)); var generation = applicationError.Contains("generation") ? applicationError["generation"].AsInt32 : 0; mockConnection.SetupGet(c => c.Generation).Returns(generation); var when = applicationError["when"].AsString; switch (when) { case "beforeHandshakeCompletes": server.HandleBeforeHandshakeCompletesException(mockConnection.Object, simulatedException); break; case "afterHandshakeCompletes": server.HandleChannelException(mockConnection.Object, simulatedException); break; default: throw new ArgumentException($"Unsupported value of {when} for when."); } }
public void HandleChannelException_should_update_topology_as_expected_on_network_error_or_timeout( string errorType, bool shouldUpdateTopology) { var serverId = new ServerId(_clusterId, _endPoint); var connectionId = new ConnectionId(serverId); Exception innerMostException; switch (errorType) { case "MongoConnectionExceptionWithSocketTimeout": innerMostException = new SocketException((int)SocketError.TimedOut); break; case nameof(MongoConnectionException): innerMostException = new SocketException((int)SocketError.NetworkUnreachable); break; default: throw new ArgumentException("Unknown error type."); } var operationUsingChannelException = new MongoConnectionException(connectionId, "Oops", new IOException("Cry", innerMostException)); var mockConnection = new Mock <IConnectionHandle>(); var isMasterResult = new IsMasterResult(new BsonDocument { { "compressors", new BsonArray() } }); // the server version doesn't matter when we're not testing MongoNotPrimaryExceptions, but is needed when // Server calls ShouldClearConnectionPoolForException var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", "4.4.0" } }); mockConnection.SetupGet(c => c.Description) .Returns(new ConnectionDescription(new ConnectionId(serverId, 0), isMasterResult, buildInfoResult)); var mockConnectionPool = new Mock <IConnectionPool>(); mockConnectionPool.Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>())).Returns(mockConnection.Object); mockConnectionPool.Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>())).ReturnsAsync(mockConnection.Object); var mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>(); mockConnectionPoolFactory .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint)) .Returns(mockConnectionPool.Object); var mockMonitorServerInitialDescription = new ServerDescription(serverId, _endPoint).With(reasonChanged: "Initial D", type: ServerType.Unknown); var mockServerMonitor = new Mock <IServerMonitor>(); mockServerMonitor.SetupGet(m => m.Description).Returns(mockMonitorServerInitialDescription); mockServerMonitor.SetupGet(m => m.Lock).Returns(new object()); var mockServerMonitorFactory = new Mock <IServerMonitorFactory>(); mockServerMonitorFactory.Setup(f => f.Create(It.IsAny <ServerId>(), _endPoint)).Returns(mockServerMonitor.Object); var subject = new DefaultServer(_clusterId, _clusterClock, _clusterConnectionMode, _connectionModeSwitch, _directConnection, _settings, _endPoint, mockConnectionPoolFactory.Object, mockServerMonitorFactory.Object, _capturedEvents, _serverApi); subject.Initialize(); var heartbeatDescription = mockMonitorServerInitialDescription.With(reasonChanged: "Heartbeat", type: ServerType.Standalone); mockServerMonitor.Setup(m => m.Description).Returns(heartbeatDescription); mockServerMonitor.Raise( m => m.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(mockMonitorServerInitialDescription, heartbeatDescription)); subject.Description.Should().Be(heartbeatDescription); subject.HandleChannelException(mockConnection.Object, operationUsingChannelException); if (shouldUpdateTopology) { subject.Description.Type.Should().Be(ServerType.Unknown); subject.Description.ReasonChanged.Should().Contain("ChannelException"); } else { subject.Description.Should().Be(heartbeatDescription); } }