public void ShouldNotThrowExceptionWhenIdlePoolSizeReached() { var connectionPoolSettings = new ConnectionPoolSettings(2, Config.Infinite); var pool = new ConnectionPool(MockedConnection, settings: connectionPoolSettings); pool.Acquire(); pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(2); var ex = Record.Exception(() => pool.Acquire()); ex.Should().BeNull(); }
public void ShouldNotThrowExceptionWhenIdlePoolSizeReached() { var config = new Config { MaxIdleSessionPoolSize = 2 }; var pool = new ConnectionPool(MockedConnection, config: config); pool.Acquire(); pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(2); var ex = Record.Exception(() => pool.Acquire()); ex.Should().BeNull(); }
public void ShouldCloseAcquiredConnectionIfPoolDisposeStarted() { // Given var conns = new ConcurrentQueue <IPooledConnection>(); var healthyMock = new Mock <IPooledConnection>(); var pool = new ConnectionPool(MockedConnection, conns); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(0); // This is to simulate Acquire called first, // but before Acquire put a new conn into inUseConn, Dispose get called. // Note: Once dispose get called, it is forbiden to put anything into queue. healthyMock.Setup(x => x.IsOpen).Returns(true) .Callback(() => pool.DisposeCalled = true); // Simulte Dispose get called at this time conns.Enqueue(healthyMock.Object); pool.NumberOfAvailableConnections.Should().Be(1); // When var exception = Record.Exception(() => pool.Acquire()); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(0); healthyMock.Verify(x => x.IsOpen, Times.Once); healthyMock.Verify(x => x.Close(), Times.Once); exception.Should().BeOfType <ObjectDisposedException>(); exception.Message.Should().StartWith("Failed to acquire a new connection"); }
/// <summary> /// Asynchrounously executes an operation for a given key. /// </summary> /// <param name="operation">The <see cref="IOperation{T}" /> being executed.</param> /// <returns> /// An <see cref="IOperationResult" /> representing the result of operation. /// </returns> /// <remarks> /// This overload is used to perform authentication on the connection if it has not already been authenticated. /// </remarks> public override async Task ExecuteAsync(IOperation operation) { ExceptionDispatchInfo capturedException = null; IConnection connection = null; try { connection = ConnectionPool.Acquire(); Log.Trace("Using conn {0} on {1}", connection.Identity, connection.EndPoint); //A new connection will have to check for server features CheckEnabledServerFeatures(connection); await ExecuteAsync(operation, connection); } catch (Exception e) { Log.Debug(e); capturedException = ExceptionDispatchInfo.Capture(e); } finally { ConnectionPool.Release(connection); } if (capturedException != null) { await HandleException(capturedException, operation); } }
/// <summary> /// Executes raw sql directly against the database with no parameterization or pooling. /// Only use this for quick one-off queries, such as queries to run during load/unload of the server or editor-specific tasks. /// </summary> /// <param name="sqls">The sql queries to execute. Gets wrapped up in a transaction.</param> public override void ExecuteNonQueries(params string[] sqls) { using (var conn = ConnectionPool.Acquire()) { using (var trans = conn.Connection.BeginTransaction()) { try { using (var dbCommand = conn.Connection.CreateCommand()) { dbCommand.Connection = conn.Connection; dbCommand.Transaction = trans; foreach (string sql in sqls) { dbCommand.CommandText = sql; dbCommand.ExecuteNonQuery(); } trans.Commit(); } } catch { trans.Rollback(); throw; } } } }
public void ShouldReuseIdleNotTooLongConn() { // Given var mock = new Mock <IPooledConnection>(); mock.Setup(x => x.IsOpen).Returns(true); var timerMock = new Mock <ITimer>(); timerMock.Setup(x => x.ElapsedMilliseconds).Returns(10); mock.Setup(x => x.IdleTimer).Returns(timerMock.Object); var idleTooLongId = Guid.NewGuid(); mock.Setup(x => x.Id).Returns(idleTooLongId); var conns = new ConcurrentQueue <IPooledConnection>(); conns.Enqueue(mock.Object); var enableIdleTooLongTest = TimeSpan.FromMilliseconds(100); var poolSettings = new ConnectionPoolSettings(2, enableIdleTooLongTest); var pool = new ConnectionPool(MockedConnection, conns, settings: poolSettings); pool.NumberOfAvailableConnections.Should().Be(1); pool.NumberOfInUseConnections.Should().Be(0); // When var conn = pool.Acquire(); // Then pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(1); conn.Should().Be(mock.Object); conn.Id.Should().Be(idleTooLongId); }
/// <summary> /// Executes an operation for a given key. /// </summary> /// <param name="operation">The <see cref="IOperation" /> being executed.</param> /// <returns> /// An <see cref="IOperationResult" /> representing the result of operation. /// </returns> /// <exception cref="System.NotImplementedException"></exception> public IOperationResult Execute(IOperation operation) { //Get the buffer and a connection var request = operation.Write(); var connection = ConnectionPool.Acquire(); byte[] response; try { //A new connection will have to be authenticated if (!connection.IsAuthenticated) { Authenticate(connection); } //Send the request buffer and release the connection response = connection.Send(request); } finally { ConnectionPool.Release(connection); } //Read the response and return the completed operation if (response != null) { operation.Read(response, 0, response.Length); } return(operation.GetResult()); }
public void When_Connecting_To_Dead_IP_Connection_Fails_After_n_Seconds() { const int connectionTimedOut = 10060; const string ipThatDoesNotExist = "198.0.0.1:11210"; var ipEndpoint = UriExtensions.GetEndPoint(ipThatDoesNotExist); var connectionPoolConfig = new PoolConfiguration { ConnectTimeout = 1000 //set really low for test }; var connectionPool = new ConnectionPool <Connection>(connectionPoolConfig, ipEndpoint); var stopWatch = new Stopwatch(); try { stopWatch.Start(); var connection = connectionPool.Acquire(); } catch (SocketException e) { Assert.AreEqual(connectionTimedOut, e.ErrorCode); } finally { stopWatch.Stop(); Assert.AreEqual(1.0d, Math.Round((double)stopWatch.Elapsed.Seconds)); } }
public void ShouldReuseOpenConnectionWhenOpenAndClosedConnectionsInQueue() { var conns = new ConcurrentQueue <IPooledConnection>(); var healthyMock = new Mock <IPooledConnection>(); healthyMock.Setup(x => x.IsOpen).Returns(true); var unhealthyMock = new Mock <IPooledConnection>(); unhealthyMock.Setup(x => x.IsOpen).Returns(false); conns.Enqueue(unhealthyMock.Object); conns.Enqueue(healthyMock.Object); var pool = new ConnectionPool(MockedConnection, conns); pool.NumberOfAvailableConnections.Should().Be(2); pool.NumberOfInUseConnections.Should().Be(0); var conn = pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(1); unhealthyMock.Verify(x => x.Close(), Times.Once); healthyMock.Verify(x => x.Close(), Times.Never); conn.Should().Be(healthyMock.Object); }
public void ShouldCreateNewWhenQueueOnlyContainsClosedConnections() { var conns = new ConcurrentQueue <IPooledConnection>(); var closedId = Guid.NewGuid(); var closedMock = new Mock <IPooledConnection>(); closedMock.Setup(x => x.IsOpen).Returns(false); closedMock.Setup(x => x.Id).Returns(closedId); conns.Enqueue(closedMock.Object); var pool = new ConnectionPool(MockedConnection, conns); pool.NumberOfAvailableConnections.Should().Be(1); pool.NumberOfInUseConnections.Should().Be(0); var conn = pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(1); closedMock.Verify(x => x.IsOpen, Times.Once); closedMock.Verify(x => x.Close(), Times.Once); conn.Should().NotBeNull(); conn.Id.Should().NotBe(closedId); }
public void When_Connecting_To_Good_IP_Connection_Succeeds_Before_ConnectTimeout() { const int connectionTimedOut = 10060; string ipThatDoesExist = ConfigurationManager.AppSettings["OperationTestAddress"]; var ipEndpoint = UriExtensions.GetEndPoint(ipThatDoesExist); var connectionPoolConfig = new PoolConfiguration { ConnectTimeout = 5000 //set really low for test }; var connectionPool = new ConnectionPool <Connection>(connectionPoolConfig, ipEndpoint); IConnection connection = null; var stopWatch = new Stopwatch(); try { stopWatch.Start(); connection = connectionPool.Acquire(); } catch (SocketException e) { Assert.AreEqual(connectionTimedOut, e.ErrorCode); } finally { stopWatch.Stop(); Assert.IsNotNull(connection); Assert.IsTrue(connection.Socket.Connected); connection.Dispose(); } }
/// <summary> /// Executes an operation for a given key. /// </summary> /// <typeparam name="T">The Type T of the value being stored or retrieved.</typeparam> /// <param name="operation">The <see cref="IOperation{T}" /> being executed.</param> /// <returns> /// An <see cref="IOperationResult{T}" /> representing the result of operation. /// </returns> public override IOperationResult <T> Execute <T>(IOperation <T> operation) { var connection = ConnectionPool.Acquire(); Log.Trace("Using conn {0} on {1}", connection.Identity, connection.EndPoint); try { //A new connection will have to check for server features CheckEnabledServerFeatures(connection); var request = operation.Write(Tracer, ConnectionPool.Configuration.BucketName); byte[] response; OperationHeader header; ErrorCode errorCode; using (var span = Tracer.BuildSpan(operation, connection, ConnectionPool.Configuration.BucketName).Start()) { response = connection.Send(request); header = response.CreateHeader(ErrorMap, out errorCode); span.SetPeerLatencyTag(header.GetServerDuration(response)); } operation.Read(response, header, errorCode); } catch (SocketException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.TransportFailure); } catch (AuthenticationException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.AuthenticationError); } catch (RemoteHostTimeoutException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.TransportFailure); //this almost always will be a server offline or service down ConnectionPool.Owner.MarkDead(); } catch (Exception e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.ClientFailure); } finally { ConnectionPool.Release(connection); } return(operation.GetResultWithValue(Tracer, ConnectionPool.Configuration.BucketName)); }
public void ShouldCreateNewWhenQueueIsEmpty() { var pool = new ConnectionPool(MockedConnection); pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(1); }
public async Task ExecuteAsync(IOperation operation) { var buffer = await operation.WriteAsync(); var connection = ConnectionPool.Acquire(); connection.SendAsync(buffer, operation.Completed); }
/// <summary> /// Gets an available <see cref="IPoolableDbConnection"/> from the <see cref="IDbQuery.ConnectionPool"/>. /// </summary> /// <returns>A free <see cref="IPoolableDbConnection"/>.</returns> /// <exception cref="MethodAccessException">Can not access methods on a disposed object.</exception> protected IPoolableDbConnection GetPoolableConnection() { if (_disposed) { throw new MethodAccessException(_disposedErrorMessage); } return(ConnectionPool.Acquire()); }
public void ShouldThrowExceptionWhenAcquireCalledAfterDispose() { var pool = new ConnectionPool(MockedConnection); pool.Dispose(); var exception = Record.Exception(() => pool.Acquire()); exception.Should().BeOfType <InvalidOperationException>(); exception.Message.Should().Contain("the driver has already been disposed"); }
public void ShouldThrowExceptionWhenAcquireCalledAfterDispose() { var pool = new ConnectionPool(MockedConnection); pool.Dispose(); var exception = Record.Exception(() => pool.Acquire()); exception.Should().BeOfType <ObjectDisposedException>(); exception.Message.Should().StartWith("Failed to acquire a new connection"); }
/// <summary> /// Asynchrounously executes an operation for a given key. /// </summary> /// <param name="operation">The <see cref="IOperation{T}" /> being executed.</param> /// <returns> /// An <see cref="IOperationResult" /> representing the result of operation. /// </returns> /// <exception cref="System.NotImplementedException"></exception> /// <remarks> /// This overload is used to perform authentication on the connection if it has not already been authenticated. /// </remarks> public Task ExecuteAsync(IOperation operation) { var connection = ConnectionPool.Acquire(); if (!connection.IsAuthenticated) { Authenticate(connection); } return(ExecuteAsync(operation, connection)); }
/// <summary> /// Executes an operation for a given key. /// </summary> /// <typeparam name="T">The Type T of the value being stored or retrieved.</typeparam> /// <param name="operation">The <see cref="IOperation{T}" /> being executed.</param> /// <returns> /// An <see cref="IOperationResult{T}" /> representing the result of operation. /// </returns> public override IOperationResult <T> Execute <T>(IOperation <T> operation) { //Get the buffer and a connection var request = operation.Write(); var connection = ConnectionPool.Acquire(); Log.Trace("Using conn {0} on {1}", connection.Identity, connection.EndPoint); byte[] response = null; try { //A new connection will have to check for server features CheckEnabledServerFeatures(connection); //Send the request buffer and release the connection response = connection.Send(request); } catch (SocketException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.TransportFailure); } catch (AuthenticationException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.AuthenticationError); } catch (RemoteHostTimeoutException e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.TransportFailure); //this almost always will be a server offline or service down ConnectionPool.Owner.MarkDead(); } catch (Exception e) { Log.Debug(e); operation.Exception = e; operation.HandleClientError(e.Message, ResponseStatus.ClientFailure); } finally { ConnectionPool.Release(connection); } operation.Read(response, ErrorMap); return(operation.GetResultWithValue()); }
public void Test() { ObjectPool <Connection> objectPool = new ConnectionPool("connection string", "username", "password"); var connection1 = objectPool.Acquire(); Assert.That(connection1, Is.Not.Null); Assert.That(connection1, Is.TypeOf <Connection>()); var connection2 = objectPool.Acquire(); Assert.That(connection2, Is.Not.Null); Assert.That(connection2, Is.TypeOf <Connection>()); Assert.That(connection1, Is.Not.SameAs(connection2)); objectPool.Release(connection1); var connection3 = objectPool.Acquire(); Assert.That(connection1, Is.SameAs(connection3)); }
public void Test() { ObjectPool<Connection> objectPool = new ConnectionPool("connection string", "username", "password"); var connection1 = objectPool.Acquire(); Assert.That(connection1, Is.Not.Null); Assert.That(connection1, Is.TypeOf<Connection>()); var connection2 = objectPool.Acquire(); Assert.That(connection2, Is.Not.Null); Assert.That(connection2, Is.TypeOf<Connection>()); Assert.That(connection1, Is.Not.SameAs(connection2)); objectPool.Release(connection1); var connection3 = objectPool.Acquire(); Assert.That(connection1, Is.SameAs(connection3)); }
public void ShouldCloseConnectionIfFailedToCreate() { var mockedConnection = new Mock <IConnection>(); mockedConnection.Setup(x => x.Init()).Throws(new InvalidOperationException()); var pool = new ConnectionPool(mockedConnection.Object); Record.Exception(() => pool.Acquire()); mockedConnection.Verify(x => x.Close(), Times.Once); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(0); }
public void ShouldCallConnInit() { // Given var mock = new Mock <IConnection>(); mock.Setup(x => x.IsOpen).Returns(true); var connectionPool = new ConnectionPool(mock.Object); // When connectionPool.Acquire(); //Then mock.Verify(x => x.Init(), Times.Once); }
public void ShouldAcquireFromPoolIfAvailable() { var connectionPoolSettings = new ConnectionPoolSettings(2, Config.Infinite); var pool = new ConnectionPool(MockedConnection, settings: connectionPoolSettings); for (var i = 0; i < 4; i++) { var conn = pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); conn.Dispose(); pool.NumberOfAvailableConnections.Should().Be(1); } pool.NumberOfAvailableConnections.Should().Be(1); }
/// <summary> /// Executes raw sql directly against the database with no parameterization or pooling. /// Only use this for quick one-off queries, such as queries to run during load/unload of the server or editor-specific tasks. /// </summary> /// <param name="sql">The sql to execute.</param> public override void ExecuteNonQuery(string sql) { using (var conn = ConnectionPool.Acquire()) { using (var trans = conn.Connection.BeginTransaction()) { using (var dbCommand = conn.Connection.CreateCommand()) { dbCommand.CommandText = sql; dbCommand.ExecuteNonQuery(); } trans.Commit(); } } }
public void ShouldAcquireFromPoolIfAvailable() { var config = new Config { MaxIdleSessionPoolSize = 2 }; var pool = new ConnectionPool(MockedConnection, config: config); for (var i = 0; i < 4; i++) { var conn = pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); conn.Dispose(); pool.NumberOfAvailableConnections.Should().Be(1); } pool.NumberOfAvailableConnections.Should().Be(1); }
public void ShouldAddExternalConnectionHandlerIfNotNull() { // Given var mock = new Mock <IConnection>(); mock.Setup(x => x.IsOpen).Returns(true); var mockedHandler = new Mock <IConnectionErrorHandler>(); var connectionPool = new ConnectionPool(mock.Object, exteralErrorHandler: mockedHandler.Object); // When connectionPool.Acquire(); //Then mock.Verify(x => x.AddConnectionErrorHander(mockedHandler.Object), Times.Once); mock.Verify(x => x.Init(), Times.Once); }
public void ShouldReuseWhenOpenConnectionInQueue() { var conns = new ConcurrentQueue <IPooledConnection>(); var mock = new Mock <IPooledConnection>(); mock.Setup(x => x.IsOpen).Returns(true); conns.Enqueue(mock.Object); var pool = new ConnectionPool(MockedConnection, conns); pool.NumberOfAvailableConnections.Should().Be(1); pool.NumberOfInUseConnections.Should().Be(0); var conn = pool.Acquire(); pool.NumberOfAvailableConnections.Should().Be(0); pool.NumberOfInUseConnections.Should().Be(1); mock.Verify(x => x.IsOpen, Times.Once); conn.Should().Be(mock.Object); }
public void ShouldNotExceedIdleLimit() { var connectionPoolSettings = new ConnectionPoolSettings(2, Config.Infinite); var pool = new ConnectionPool(MockedConnection, settings: connectionPoolSettings); var conns = new List <IConnection>(); for (var i = 0; i < 4; i++) { conns.Add(pool.Acquire()); pool.NumberOfAvailableConnections.Should().Be(0); } foreach (var conn in conns) { conn.Dispose(); pool.NumberOfAvailableConnections.Should().BeLessOrEqualTo(2); } pool.NumberOfAvailableConnections.Should().Be(2); }
/// <summary> /// Executes raw sql directly against the database with no parameterization or pooling. /// Only use this for quick one-off queries, such as queries to run during load/unload of the server or editor-specific tasks. /// </summary> /// <param name="sql">The sql to execute.</param> /// <param name="readFunc">The function used to describe how to the results of each row.</param> /// <typeparam name="T">The return type for read rows.</typeparam> public override List <T> ExecuteQuery <T>(string sql, Func <DbDataReader, T> readFunc) { List <T> ret = new List <T>(); using (var conn = ConnectionPool.Acquire()) { using (var dbCommand = conn.Connection.CreateCommand()) { dbCommand.CommandText = sql; using (var r = dbCommand.ExecuteReader()) { while (r.Read()) { ret.Add(readFunc(r)); } } } } return(ret); }
/// <summary> /// Executes only read-only SQL. /// </summary> /// <returns>The query.</returns> /// <param name="sql">Sql.</param> /// <param name="paramArgs">Parameter arguments.</param> public Cursor RawQuery(String sql, params Object[] paramArgs) { if (!IsOpen) { throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadRequest, TAG, "RawQuery called on closed database"); } Cursor cursor = null; sqlite3_stmt command = null; var connection = default(Connection); //Log.To.TaskScheduling.V(TAG, "Scheduling RawQuery"); //var t = Factory.StartNew (() => //{ Log.To.TaskScheduling.V(TAG, "Running RawQuery"); try { connection = IsOnDBThread ? new Connection(_writeConnection, null) : _readerConnections.Acquire(); Log.To.Database.V(TAG, "RawQuery sql ({2}): {0} ({1})", sql, String.Join(", ", paramArgs.ToStringArray()), IsOnDBThread ? "read uncommit" : "read commit"); command = BuildCommand(connection.Raw, sql, paramArgs); cursor = new Cursor(command, connection); } catch (Exception e) { if (command != null) { command.Dispose(); } var args = new SecureLogJsonString(paramArgs, LogMessageSensitivity.PotentiallyInsecure); Log.To.Database.E(TAG, String.Format("Error executing raw query '{0}' with values '{1}', rethrowing...", sql, paramArgs == null ? (object)String.Empty : new SecureLogJsonString(args, LogMessageSensitivity.PotentiallyInsecure)), e); LastErrorCode = raw.sqlite3_errcode(connection.Raw); throw; } return(cursor); //}); //return t.Result; }
public void When_Connecting_To_Good_IP_Connection_Succeeds_Before_ConnectTimeout() { const int connectionTimedOut = 10060; string ipThatDoesExist = ConfigurationManager.AppSettings["OperationTestAddress"]; var ipEndpoint = UriExtensions.GetEndPoint(ipThatDoesExist); var connectionPoolConfig = new PoolConfiguration { ConnectTimeout = 5000 //set really low for test }; var connectionPool = new ConnectionPool<Connection>(connectionPoolConfig, ipEndpoint); IConnection connection = null; var stopWatch = new Stopwatch(); try { stopWatch.Start(); connection = connectionPool.Acquire(); } catch (SocketException e) { Assert.AreEqual(connectionTimedOut, e.ErrorCode); } finally { stopWatch.Stop(); Assert.IsNotNull(connection); Assert.IsTrue(connection.Socket.Connected); connection.Dispose(); } }
public void When_Connecting_To_Dead_IP_Connection_Fails_After_n_Seconds() { const int connectionTimedOut = 10060; const string ipThatDoesNotExist = "198.0.0.1:11210"; var ipEndpoint = UriExtensions.GetEndPoint(ipThatDoesNotExist); var connectionPoolConfig = new PoolConfiguration { ConnectTimeout = 1000 //set really low for test }; var connectionPool = new ConnectionPool<Connection>(connectionPoolConfig, ipEndpoint); var stopWatch = new Stopwatch(); try { stopWatch.Start(); var connection = connectionPool.Acquire(); } catch (SocketException e) { Assert.AreEqual(connectionTimedOut, e.ErrorCode); } finally { stopWatch.Stop(); Assert.AreEqual(1.0d, Math.Round((double)stopWatch.Elapsed.Seconds)); } }