public void ThrowIfExpired_should_not_throw_when_the_timeout_has_not_expired() { var subject = new SlidingTimeout(TimeSpan.FromSeconds(10), _clock); Action act = () => subject.ThrowIfExpired(); act.ShouldNotThrow(); }
// methods public async Task AuthenticateAsync(IConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { using (var conversation = new SaslConversation()) { var currentStep = _mechanism.Initialize(connection); var command = new BsonDocument { { "saslStart", 1 }, { "mechanism", _mechanism.Name }, { "payload", currentStep.BytesToSendToServer } }; var slidingTimeout = new SlidingTimeout(timeout); while (true) { BsonDocument result; try { var protocol = new CommandWireProtocol(new DatabaseNamespace(DatabaseName), command, true, null); result = await protocol.ExecuteAsync(connection, slidingTimeout, cancellationToken); } catch(MongoCommandException ex) { var message = string.Format("Unable to authenticate using sasl protocol mechanism {0}.", Name); throw new MongoAuthenticationException(message, ex); } // we might be done here if the client is not expecting a reply from the server if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } currentStep = currentStep.Transition(conversation, result["payload"].AsByteArray); // we might be done here if the client had some final verification it needed to do if (result.GetValue("done", false).ToBoolean() && currentStep.IsComplete) { break; } command = new BsonDocument { { "saslContinue", 1 }, { "conversationId", result["conversationId"].AsInt32 }, { "payload", currentStep.BytesToSendToServer } }; } } }
public async Task AuthenticateAsync(IConnection connection, TimeSpan timeout, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, "connection"); try { var slidingTimeout = new SlidingTimeout(timeout); var nonce = await GetNonceAsync(connection, slidingTimeout, cancellationToken); await AuthenticateAsync(connection, nonce, slidingTimeout, cancellationToken); } catch(MongoCommandException ex) { var message = string.Format("Unable to authenticate username '{0}' on database '{1}'.", _credential.Username, _credential.Source); throw new MongoAuthenticationException(message, ex); } }
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); }
// 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); 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; }
public void Expiration_should_be_DateTime_Max_when_timeout_is_zero() { var subject = new SlidingTimeout(TimeSpan.Zero); subject.Expiration.Should().Be(DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc)); }
// 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); 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 } } } }
public async Task<BulkWriteResult> ExecuteAsync(IConnectionHandle connection, TimeSpan timeout, CancellationToken cancellationToken) { var slidingTimeout = new SlidingTimeout(timeout); var batchResults = new List<BulkWriteBatchResult>(); var remainingRequests = new List<WriteRequest>(); var hasWriteErrors = false; var originalIndex = 0; foreach (WriteRequest request in _requests) { if (hasWriteErrors && _isOrdered) { remainingRequests.Add(request); continue; } var batchResult = await EmulateSingleRequestAsync(connection, request, originalIndex, slidingTimeout, cancellationToken); batchResults.Add(batchResult); hasWriteErrors |= batchResult.HasWriteErrors; originalIndex++; } var combiner = new BulkWriteBatchResultCombiner(batchResults, !_writeConcern.Equals(WriteConcern.Unacknowledged)); return combiner.CreateResultOrThrowIfHasErrors(remainingRequests); }
public void ToTimeout_should_return_infinite_TimeSpan_when_expiration_is_MaxValue() { var subject = new SlidingTimeout(Timeout.InfiniteTimeSpan); subject.ToTimeout().Should().Be(Timeout.InfiniteTimeSpan); }
public void Expiration_should_be_DateTime_Max_when_timeout_is_infinite() { var subject = new SlidingTimeout(Timeout.InfiniteTimeSpan); subject.Expiration.Should().Be(DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc)); }
public void Expiration_should_be_UtcNow_plus_timeout() { var subject = new SlidingTimeout(TimeSpan.FromSeconds(10), _clock); subject.Expiration.Should().Be(_clock.UtcNow.AddSeconds(10)); }
public void ThrowIfExpired_should_throw_when_the_timeout_has_expired() { var subject = new SlidingTimeout(TimeSpan.FromSeconds(10), _clock); _clock.UtcNow = _clock.UtcNow.AddSeconds(11); Action act = () => subject.ThrowIfExpired(); act.ShouldThrow<TimeoutException>(); }
public void ToTimeout_should_throw_a_TimeoutException_when_the_timeout_has_expired() { var subject = new SlidingTimeout(TimeSpan.FromMilliseconds(20), _clock); _clock.UtcNow = _clock.UtcNow.AddMilliseconds(30); Action act = () => subject.ToTimeout(); act.ShouldThrow<TimeoutException>(); }
public void ToTimeout_should_return_the_amount_of_time_left() { var subject = new SlidingTimeout(TimeSpan.FromMilliseconds(20), _clock); subject.ToTimeout().Should().Be(TimeSpan.FromMilliseconds(20)); _clock.UtcNow = _clock.UtcNow.AddMilliseconds(10); subject.ToTimeout().Should().Be(TimeSpan.FromMilliseconds(10)); _clock.UtcNow = _clock.UtcNow.AddMilliseconds(10); subject.ToTimeout().Should().Be(TimeSpan.Zero); }
public async Task<IServer> SelectServerAsync(IServerSelector selector, TimeSpan timeout, CancellationToken cancellationToken) { ThrowIfDisposedOrNotOpen(); Ensure.IsNotNull(selector, "selector"); var slidingTimeout = new SlidingTimeout(timeout); while (true) { cancellationToken.ThrowIfCancellationRequested(); Task descriptionChangedTask; ClusterDescription description; lock (_descriptionLock) { descriptionChangedTask = _descriptionChangedTaskCompletionSource.Task; description = _description; } ThrowIfIncompatible(description); var connectedServers = description.Servers.Where(s => s.State == ServerState.Connected); var selectedServers = selector.SelectServers(description, connectedServers).ToList(); while (selectedServers.Count > 0) { var server = selectedServers.Count == 1 ? selectedServers[0] : __randomServerSelector.SelectServers(description, selectedServers).Single(); IClusterableServer selectedServer; if (TryGetServer(server.EndPoint, out selectedServer)) { return selectedServer; } selectedServers.Remove(server); } Invalidate(); await descriptionChangedTask.WithTimeout(slidingTimeout, cancellationToken); } }