Exemple #1
0
        // methods
        public async Task <Stream> CreateStreamAsync(EndPoint endPoint, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var slidingTimeout = new SlidingTimeout(timeout);
            var addressFamily  = endPoint.AddressFamily;

            if (addressFamily == AddressFamily.Unspecified || addressFamily == AddressFamily.Unknown)
            {
                addressFamily = _settings.AddressFamily;
            }
            var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);

            await ConnectAsync(socket, endPoint, slidingTimeout, cancellationToken).ConfigureAwait(false);

            socket.NoDelay           = true;
            socket.ReceiveBufferSize = _settings.ReceiveBufferSize;
            socket.SendBufferSize    = _settings.SendBufferSize;

            var stream = new NetworkStream(socket, true);

            if (_settings.ReadTimeout.HasValue)
            {
                var readTimeout = (int)_settings.ReadTimeout.Value.TotalMilliseconds;
                if (readTimeout != 0)
                {
                    stream.ReadTimeout = readTimeout;
                }
            }

            if (_settings.WriteTimeout.HasValue)
            {
                var writeTimeout = (int)_settings.WriteTimeout.Value.TotalMilliseconds;
                if (writeTimeout != 0)
                {
                    stream.WriteTimeout = writeTimeout;
                }
            }

            return(stream);
        }
Exemple #2
0
        private async Task OpenAsyncHelper(TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (_listener != null)
            {
                _listener.ConnectionBeforeOpening(_connectionId, _settings);
            }

            try
            {
                var slidingTimeout = new SlidingTimeout(timeout);
                var stopwatch      = Stopwatch.StartNew();
                _stream = await _streamFactory.CreateStreamAsync(_endPoint, slidingTimeout, cancellationToken);

                _state.TryChange(State.Initializing);
                StartBackgroundTasks();
                _description = await _connectionInitializer.InitializeConnectionAsync(this, _connectionId, slidingTimeout, cancellationToken);

                stopwatch.Stop();
                _connectionId = _description.ConnectionId;
                _state.TryChange(State.Open);

                if (_listener != null)
                {
                    _listener.ConnectionAfterOpening(_connectionId, _settings, stopwatch.Elapsed);
                }
            }
            catch (Exception ex)
            {
                _state.TryChange(State.Failed);

                if (_listener != null)
                {
                    _listener.ConnectionErrorOpening(_connectionId, ex);
                    _listener.ConnectionFailed(_connectionId, ex);
                }

                throw;
            }
        }
Exemple #3
0
        public async Task <BsonDocument> ExecuteAsync(IConnection connection, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var slidingTimeout = new SlidingTimeout(timeout);

            var writeMessage = CreateWriteMessage(connection);

            if (_writeConcern.Equals(WriteConcern.Unacknowledged))
            {
                await connection.SendMessageAsync(writeMessage, slidingTimeout, cancellationToken);

                return(null);
            }
            else
            {
                var getLastErrorMessage = CreateGetLastErrorMessage();
                await connection.SendMessagesAsync(new RequestMessage[] { writeMessage, getLastErrorMessage }, slidingTimeout, cancellationToken);

                var reply = await connection.ReceiveMessageAsync <BsonDocument>(getLastErrorMessage.RequestId, BsonDocumentSerializer.Instance, slidingTimeout, cancellationToken);

                return(ProcessReply(reply));
            }
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        private async Task <BulkWriteOperationResult> ExecuteBatchesAsync(IConnectionHandle connection, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var slidingTimeout    = new SlidingTimeout(timeout);
            var batchResults      = new List <BulkWriteBatchResult>();
            var remainingRequests = Enumerable.Empty <WriteRequest>();
            var hasWriteErrors    = false;

            var decoratedRequests = DecorateRequests(_requests);

            using (var enumerator = decoratedRequests.GetEnumerator())
            {
                var originalIndex = 0;

                var requestSource = new BatchableSource <WriteRequest>(enumerator);
                while (requestSource.HasMore)
                {
                    if (hasWriteErrors && _isOrdered)
                    {
                        // note: we have to materialize the list of remaining items before the enumerator gets Disposed
                        remainingRequests = remainingRequests.Concat(requestSource.GetRemainingItems()).ToList();
                        break;
                    }

                    var batchResult = await ExecuteBatchAsync(connection, requestSource, originalIndex, slidingTimeout, cancellationToken).ConfigureAwait(false);

                    batchResults.Add(batchResult);
                    hasWriteErrors |= batchResult.HasWriteErrors;
                    originalIndex  += batchResult.BatchCount;

                    requestSource.ClearBatch();
                }
            }

            var combiner = new BulkWriteBatchResultCombiner(batchResults, _writeConcern.IsAcknowledged);

            return(combiner.CreateResultOrThrowIfHasErrors(remainingRequests.ToList()));
        }
Exemple #6
0
        // methods
        public async Task <BulkWriteOperationResult> ExecuteAsync(IConnectionHandle connection, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var slidingTimeout    = new SlidingTimeout(timeout);
            var batchResults      = new List <BulkWriteBatchResult>();
            var remainingRequests = Enumerable.Empty <WriteRequest>();
            var hasWriteErrors    = false;

            var runCount     = 0;
            var maxRunLength = Math.Min(_maxBatchCount ?? int.MaxValue, connection.Description.MaxBatchCount);

            foreach (var run in FindRuns(maxRunLength))
            {
                runCount++;

                if (hasWriteErrors && _isOrdered)
                {
                    remainingRequests = remainingRequests.Concat(run.Requests);
                    continue;
                }

                var batchResult = await ExecuteBatchAsync(connection, run, slidingTimeout, cancellationToken).ConfigureAwait(false);

                batchResults.Add(batchResult);

                hasWriteErrors |= batchResult.HasWriteErrors;
            }

            if (runCount == 0)
            {
                throw new InvalidOperationException("Bulk write operation is empty.");
            }

            var combiner = new BulkWriteBatchResultCombiner(batchResults, _writeConcern.IsAcknowledged);

            return(combiner.CreateResultOrThrowIfHasErrors(remainingRequests.ToList()));
        }
        // public methods
        public async Task <IConnectionHandle> AcquireConnectionAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            ThrowIfNotOpen();

            var slidingTimeout = new SlidingTimeout(timeout);

            bool enteredWaitQueue = false;
            bool enteredPool      = false;

            Stopwatch stopwatch = new Stopwatch();

            try
            {
                if (_listener != null)
                {
                    _listener.ConnectionPoolBeforeEnteringWaitQueue(_serverId);
                }

                stopwatch.Start();
                enteredWaitQueue = _waitQueue.Wait(0); // don't wait...
                if (!enteredWaitQueue)
                {
                    throw new MongoException("Too many waiters in the connection pool.");
                }
                stopwatch.Stop();

                if (_listener != null)
                {
                    _listener.ConnectionPoolAfterEnteringWaitQueue(_serverId, stopwatch.Elapsed);
                    _listener.ConnectionPoolBeforeCheckingOutAConnection(_serverId);
                }

                stopwatch.Restart();
                var waitQueueTimeout = (int)Math.Min(slidingTimeout.ToTimeout().TotalMilliseconds, timeout.TotalMilliseconds);
                if (waitQueueTimeout == Timeout.Infinite)
                {
                    // if one of these is infinite (-1), then we don't timeout properly
                    waitQueueTimeout = (int)Math.Max(slidingTimeout.ToTimeout().TotalMilliseconds, timeout.TotalMilliseconds);
                }
                enteredPool = await _poolQueue.WaitAsync(TimeSpan.FromMilliseconds(waitQueueTimeout), cancellationToken).ConfigureAwait(false);

                if (enteredPool)
                {
                    var acquired = AcquireConnection();
                    stopwatch.Stop();
                    if (_listener != null)
                    {
                        _listener.ConnectionPoolAfterCheckingOutAConnection(acquired.ConnectionId, stopwatch.Elapsed);
                    }
                    return(acquired);
                }

                stopwatch.Stop();
                var message = string.Format("Timed out waiting for a connection after {0}ms.", stopwatch.ElapsedMilliseconds);
                throw new TimeoutException(message);
            }
            catch (Exception ex)
            {
                if (enteredPool)
                {
                    try
                    {
                        _poolQueue.Release();
                    }
                    catch
                    {
                        // TODO: log this, but don't throw... it's a bug if we get here
                    }
                }

                if (_listener != null)
                {
                    if (!enteredWaitQueue)
                    {
                        _listener.ConnectionPoolErrorEnteringWaitQueue(_serverId, stopwatch.Elapsed, ex);
                    }
                    else
                    {
                        _listener.ConnectionPoolErrorCheckingOutAConnection(_serverId, stopwatch.Elapsed, ex);
                    }
                }
                throw;
            }
            finally
            {
                if (enteredWaitQueue)
                {
                    try
                    {
                        _waitQueue.Release();
                    }
                    catch
                    {
                        // TODO: log this, but don't throw... it's a bug if we get here
                    }
                }
            }
        }