Ejemplo n.º 1
0
        // methods
        internal override BsonDocument CreateCommand(ICoreSessionHandle session, ConnectionDescription connectionDescription, long?transactionNumber)
        {
            var maxWireVersion = connectionDescription.MaxWireVersion;

            if (Feature.HintForFindAndModifyFeature.DriverMustThrowIfNotSupported(maxWireVersion) || (WriteConcern != null && !WriteConcern.IsAcknowledged))
            {
                if (_hint != null)
                {
                    throw new NotSupportedException($"Server version {WireVersion.GetServerVersionForErrorMessage(maxWireVersion)} does not support hints.");
                }
            }

            var writeConcern = WriteConcernHelper.GetEffectiveWriteConcern(session, WriteConcern);

            return(new BsonDocument
            {
                { "findAndModify", CollectionNamespace.CollectionName },
                { "query", _filter },
                { "update", _update },
                { "new", true, _returnDocument == ReturnDocument.After },
                { "sort", _sort, _sort != null },
                { "fields", _projection, _projection != null },
                { "upsert", true, _isUpsert },
                { "maxTimeMS", () => MaxTimeHelper.ToMaxTimeMS(_maxTime.Value), _maxTime.HasValue },
                { "writeConcern", writeConcern, writeConcern != null },
                { "bypassDocumentValidation", () => _bypassDocumentValidation.Value, _bypassDocumentValidation.HasValue },
                { "collation", () => Collation.ToBsonDocument(), Collation != null },
                { "comment", Comment, Comment != null },
                { "hint", _hint, _hint != null },
                { "arrayFilters", () => new BsonArray(_arrayFilters), _arrayFilters != null },
                { "txnNumber", () => transactionNumber, transactionNumber.HasValue },
                { "let", _let, _let != null }
            });
        }
Ejemplo n.º 2
0
        public void ToServerVersion_with_semanticVersion_should_get_correct_serverVersion(int wireVersion, int?expectedMajorVersion, int?expectedMinorVersion)
        {
            var serverVersion = WireVersion.ToServerVersion(wireVersion);

            if (expectedMajorVersion.HasValue && expectedMinorVersion.HasValue)
            {
                serverVersion.Should().Be(new SemanticVersion(expectedMajorVersion.Value, expectedMinorVersion.Value, 0));
            }
            else
            {
                serverVersion.Should().BeNull();
            }
        }
Ejemplo n.º 3
0
        // constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="ConnectionDescription"/> class.
        /// </summary>
        /// <param name="connectionId">The connection identifier.</param>
        /// <param name="helloResult">The hello result.</param>
        public ConnectionDescription(ConnectionId connectionId, HelloResult helloResult)
        {
            _connectionId = Ensure.IsNotNull(connectionId, nameof(connectionId));
            _helloResult  = Ensure.IsNotNull(helloResult, nameof(helloResult));

            _compressors     = Ensure.IsNotNull(_helloResult.Compressions, "compressions");
            _maxBatchCount   = helloResult.MaxBatchCount;
            _maxDocumentSize = helloResult.MaxDocumentSize;
            _maxMessageSize  = helloResult.MaxMessageSize;
            _maxWireVersion  = helloResult.MaxWireVersion;
            _minWireVersion  = helloResult.MinWireVersion;
            _serviceId       = helloResult.ServiceId;
            _serverVersion   = WireVersion.ToServerVersion(_maxWireVersion);
        }
        private ServerDescription CreateServerDescription(
            ServerId serverId  = null,
            EndPoint endPoint  = null,
            ServerState state  = ServerState.Disconnected,
            ServerType type    = ServerType.Unknown,
            int?maxWireVersion = null)
        {
            endPoint = endPoint ?? new DnsEndPoint("localhost", 27017);
            serverId = serverId ?? new ServerId(new ClusterId(1), endPoint);

            maxWireVersion = maxWireVersion ?? WireVersion.Server40;
            var approximateServerVersion = WireVersion.ToServerVersion(maxWireVersion.Value);

            return(new ServerDescription(serverId, endPoint, state: state, type: type, version: approximateServerVersion, wireVersionRange: new Optional <Range <int> >(new Range <int>(0, maxWireVersion.Value))));
        }
Ejemplo n.º 5
0
        public void ToServerVersion_should_throw_if_wireVersion_less_than_0()
        {
            var exception = Record.Exception(() => WireVersion.ToServerVersion(-1));

            exception.Should().BeOfType <ArgumentOutOfRangeException>().Subject.ParamName.Should().Be("wireVersion");
        }
Ejemplo n.º 6
0
 public void GetServerVersionForErrorMessage_should_return_expected_serverVersion_message(int wireVersion, string message)
 {
     WireVersion.GetServerVersionForErrorMessage(wireVersion).Should().Be(message);
 }
        private ICluster CreateMockReplicaSetCluster()
        {
            var clusterId      = new ClusterId(1);
            var endPoint       = new DnsEndPoint("localhost", 27017);
            var serverId       = new ServerId(clusterId, endPoint);
            var maxWireVersion = Feature.Transactions.FirstSupportedWireVersion;
            var servers        = new[] { new ServerDescription(serverId, endPoint, state: ServerState.Connected, type: ServerType.ReplicaSetPrimary, version: WireVersion.ToServerVersion(maxWireVersion), wireVersionRange: new Range <int>(0, maxWireVersion)) };

#pragma warning disable CS0618 // Type or member is obsolete
            var clusterDescription = new ClusterDescription(clusterId, ClusterConnectionMode.Automatic, ClusterType.ReplicaSet, servers);
#pragma warning restore CS0618 // Type or member is obsolete
            var mockCluster = new Mock <ICluster>();
            mockCluster.SetupGet(m => m.Description).Returns(clusterDescription);
            return(mockCluster.Object);
        }
Ejemplo n.º 8
0
        private void Heartbeat(CancellationToken cancellationToken)
        {
            CommandWireProtocol <BsonDocument> helloProtocol = null;
            bool processAnother = true;

            while (processAnother && !cancellationToken.IsCancellationRequested)
            {
                HelloResult heartbeatHelloResult = null;
                Exception   heartbeatException   = null;
                var         previousDescription  = _currentDescription;

                try
                {
                    IConnection connection;
                    lock (_lock)
                    {
                        connection = _connection;
                    }
                    if (connection == null)
                    {
                        var initializedConnection = InitializeConnection(cancellationToken);
                        lock (_lock)
                        {
                            if (_state.Value == State.Disposed)
                            {
                                try { initializedConnection.Dispose(); } catch { }
                                throw new OperationCanceledException("The ServerMonitor has been disposed.");
                            }
                            _connection          = initializedConnection;
                            heartbeatHelloResult = _connection.Description.HelloResult;
                        }
                    }
                    else
                    {
                        // If MoreToCome is true, that means we are streaming hello or legacy hello results and must
                        // continue using the existing helloProtocol object.
                        // Otherwise helloProtocol has either not been initialized or we may need to switch between
                        // heartbeat commands based on the last heartbeat response.
                        if (helloProtocol == null || helloProtocol.MoreToCome == false)
                        {
                            helloProtocol = InitializeHelloProtocol(connection, previousDescription?.HelloOk ?? false);
                        }
                        heartbeatHelloResult = GetHelloResult(connection, helloProtocol, cancellationToken);
                    }
                }
                catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
                {
                    return;
                }
                catch (Exception ex)
                {
                    IConnection toDispose = null;

                    lock (_lock)
                    {
                        helloProtocol = null;

                        heartbeatException = ex;
                        _roundTripTimeMonitor.Reset();

                        toDispose   = _connection;
                        _connection = null;
                    }
                    toDispose?.Dispose();
                }

                lock (_lock)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }
                }

                ServerDescription newDescription;
                if (heartbeatHelloResult != null)
                {
                    var averageRoundTripTime        = _roundTripTimeMonitor.Average;
                    var averageRoundTripTimeRounded = TimeSpan.FromMilliseconds(Math.Round(averageRoundTripTime.TotalMilliseconds));

                    newDescription = _baseDescription.With(
                        averageRoundTripTime: averageRoundTripTimeRounded,
                        canonicalEndPoint: heartbeatHelloResult.Me,
                        electionId: heartbeatHelloResult.ElectionId,
                        helloOk: heartbeatHelloResult.HelloOk,
                        lastWriteTimestamp: heartbeatHelloResult.LastWriteTimestamp,
                        logicalSessionTimeout: heartbeatHelloResult.LogicalSessionTimeout,
                        maxBatchCount: heartbeatHelloResult.MaxBatchCount,
                        maxDocumentSize: heartbeatHelloResult.MaxDocumentSize,
                        maxMessageSize: heartbeatHelloResult.MaxMessageSize,
                        replicaSetConfig: heartbeatHelloResult.GetReplicaSetConfig(),
                        state: ServerState.Connected,
                        tags: heartbeatHelloResult.Tags,
                        topologyVersion: heartbeatHelloResult.TopologyVersion,
                        type: heartbeatHelloResult.ServerType,
                        version: WireVersion.ToServerVersion(heartbeatHelloResult.MaxWireVersion),
                        wireVersionRange: new Range <int>(heartbeatHelloResult.MinWireVersion, heartbeatHelloResult.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 && heartbeatHelloResult != null && heartbeatHelloResult.TopologyVersion != null) ||
                    // connectionIsStreaming
                    (helloProtocol != null && helloProtocol.MoreToCome) ||
                    // transitionedWithNetworkError
                    (IsNetworkError(heartbeatException) && previousDescription.Type != ServerType.Unknown);
            }

            bool IsNetworkError(Exception ex)
            {
                return(ex is MongoConnectionException mongoConnectionException && mongoConnectionException.IsNetworkException);
            }
        }