// 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); }
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; } }
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)); } }
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 <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())); }
// 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 } } } }