예제 #1
0
        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
        }
예제 #4
0
        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);
        }
예제 #6
0
        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
        }
예제 #7
0
        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);
            }
        }