Skip to content

Commit

Permalink
Merge branch 'DNET-595'
Browse files Browse the repository at this point in the history
  • Loading branch information
cincuranet committed Jul 23, 2015
2 parents fb3cc72 + 911374b commit fbbb649
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 69 deletions.
@@ -1,17 +1,17 @@
/*
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.firebirdsql.org/index.php?op=doc&id=idpl
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* Copyright (c) 2013-2014 Jiri Cincura (jiri@cincura.net)
* All Rights Reserved.
*/
Expand Down Expand Up @@ -71,15 +71,15 @@ public void Dispose()
bool _disposed;
object _syncRoot;
FbConnectionString _connectionString;
Queue<Item> _available;
Stack<Item> _available;
List<FbConnectionInternal> _busy;

public Pool(FbConnectionString connectionString)
{
_disposed = false;
_syncRoot = new object();
_connectionString = connectionString;
_available = new Queue<Item>();
_available = new Stack<Item>();
_busy = new List<FbConnectionInternal>();
}

Expand All @@ -104,7 +104,7 @@ public FbConnectionInternal GetConnection(FbConnection owner)
CheckDisposedImpl();

var connection = _available.Any()
? _available.Dequeue().Connection
? _available.Pop().Connection
: CreateNewConnectionIfPossibleImpl(_connectionString, owner);
connection.SetOwningConnection(owner);
_busy.Add(connection);
Expand All @@ -120,7 +120,9 @@ public void ReleaseConnection(FbConnectionInternal connection)

var removed = _busy.Remove(connection);
if (removed)
_available.Enqueue(new Item(DateTimeOffset.UtcNow, connection));
{
_available.Push(new Item(DateTimeOffset.UtcNow, connection));
}
}
}

Expand All @@ -132,13 +134,17 @@ public void CleanupPool()

var now = DateTimeOffset.UtcNow;
var available = _available.ToArray();
if (available.Count() <= _connectionString.MinPoolSize)
return;
var keep = available.Where(x => IsAlive(_connectionString.ConnectionLifeTime, x.Created, now)).ToArray();
var keepCount = keep.Count();
if (keepCount < _connectionString.MinPoolSize)
keep = available.Except(keep).Take(_connectionString.MinPoolSize - keepCount).ToArray();
{
keep = keep.Concat(available.Except(keep).OrderByDescending(x => x.Created).Take(_connectionString.MinPoolSize - keepCount)).ToArray();
}
var release = available.Except(keep).ToArray();
release.AsParallel().ForAll(x => x.Dispose());
_available = new Queue<Item>(keep);
_available = new Stack<Item>(keep);
}
}

Expand Down
38 changes: 12 additions & 26 deletions NETProvider/src/FirebirdSql.Data.UnitTests/FbConnectionTests.cs
@@ -1,18 +1,19 @@
/*
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.firebirdsql.org/index.php?op=doc&id=idpl
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* Copyright (c) 2002, 2007 Carlos Guzman Alvarez
* Copyright (c) 2014-2015 Jiri Cincura (jiri@cincura.net)
* All Rights Reserved.
*/

Expand Down Expand Up @@ -145,7 +146,6 @@ public void FbConnectionStringBuilderTest()
[Test]
public void ConnectionPoolingTest()
{
// Using ActiveUsers as proxy for number of connections
FbConnectionStringBuilder csb = BuildConnectionStringBuilder();
csb.Pooling = true;
csb.ConnectionLifeTime = 5;
Expand All @@ -156,27 +156,20 @@ public void ConnectionPoolingTest()

int active = ActiveConnections();

// Open two connections.
Console.WriteLine("Open two connections.");
myConnection1.Open();
myConnection2.Open();

// Now there are two connections in the pool that matches the connection string.
// Return the both connections to the pool.
Console.WriteLine("Return both of the connections to the pool.");
myConnection1.Close();
myConnection2.Close();

Assert.AreEqual(active + 2, ActiveConnections());

// Clear pools
FbConnection.ClearAllPools();
}

[Test]
public void ConnectionPoolingTimeOutTest()
{
// Using ActiveUsers as proxy for number of connections
FbConnectionStringBuilder csb = BuildConnectionStringBuilder();
csb.Pooling = true;
csb.ConnectionLifeTime = 5;
Expand All @@ -200,8 +193,6 @@ public void ConnectionPoolingTimeOutTest()
System.Threading.Thread.Sleep(csb.ConnectionLifeTime * 2 * 1000);

Assert.AreEqual(active, ActiveConnections());

FbConnection.ClearAllPools();
}

[Test]
Expand Down Expand Up @@ -243,8 +234,6 @@ public void ConnectionPoolingMaxPoolSizeTest()
connections.ForEach(x => x.Dispose());
}

FbConnection.ClearAllPools();

Assert.IsTrue(thrown);
}

Expand Down Expand Up @@ -277,9 +266,6 @@ public void ConnectionPoolingMinPoolSizeTest()
System.Threading.Thread.Sleep(csb.ConnectionLifeTime * 2 * 1000);

Assert.AreEqual(active + csb.MinPoolSize, ActiveConnections());

FbConnection.ClearAllPools();

}

[Test]
Expand Down Expand Up @@ -338,7 +324,7 @@ public FbTransaction BeginTransaction(IsolationLevel level)
}
}

private int ActiveConnections()
public static int ActiveConnections()
{
using (FbConnection conn = new FbConnection(BuildConnectionString()))
{
Expand Down
25 changes: 13 additions & 12 deletions NETProvider/src/FirebirdSql.Data.UnitTests/TestsBase.cs
@@ -1,22 +1,22 @@
/*
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.firebirdsql.org/index.php?op=doc&id=idpl
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* Copyright (c) 2002, 2007 Carlos Guzman Alvarez
* All Rights Reserved.
*
*
* Contributors:
* Jiri Cincura (jiri@cincura.net)
* Jiri Cincura (jiri@cincura.net)
*/

using System;
Expand Down Expand Up @@ -110,6 +110,7 @@ public virtual void TearDown()
}
connection.Close();

FbConnection.ClearAllPools();
string cs = BuildConnectionString();
DropDatabase(cs);
}
Expand Down
90 changes: 75 additions & 15 deletions NETProvider/src/FirebirdSql.Data.UnitTests/TrackerIssuesTests.cs
@@ -1,22 +1,20 @@
/*
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.firebirdsql.org/index.php?op=doc&id=idpl
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
*
* Copyright (c) 2006 Carlos Guzman Alvarez
* Copyright (c) 2014-2015 Jiri Cincura (jiri@cincura.net)
* All Rights Reserved.
*
* Contributors:
* Jiri Cincura (jiri@cincura.net)
*/

using System;
Expand All @@ -28,6 +26,9 @@
using FirebirdSql.Data.FirebirdClient;
using FirebirdSql.Data.Isql;
using NUnit.Framework;
using System.Threading;
using System.Collections.Generic;
using System.Diagnostics;

namespace FirebirdSql.Data.UnitTests
{
Expand Down Expand Up @@ -218,8 +219,8 @@ public void DNET260()
R94 FLOAT,
R95 FLOAT )
AS
BEGIN
SUSPEND;
BEGIN
SUSPEND;
END
";
cmd.ExecuteNonQuery();
Expand Down Expand Up @@ -264,6 +265,46 @@ public void DNET274()
}
}

[Test]
public void DNET595()
{
const int NumberOfThreads = 15;

var threads = new List<Thread>();

FbConnectionStringBuilder csb = BuildConnectionStringBuilder();
csb.Pooling = true;
csb.ConnectionLifeTime = 5;
string cs = csb.ToString();

for (int i = 0; i < NumberOfThreads; i++)
{
var t = new Thread(o =>
{
for (int j = 0; j < 50; j++)
{
GetSomething(cs);
}
});
t.IsBackground = true;
t.Start();
threads.Add(t);
}
foreach (var thread in threads)
{
thread.Join();
}
Assert.AreEqual(NumberOfThreads + 1, FbConnectionTests.ActiveConnections());

var sw = new Stopwatch();
sw.Start();
while (sw.Elapsed.TotalSeconds < 60)
{
GetSomething(cs);
}
Assert.LessOrEqual(FbConnectionTests.ActiveConnections(), 2 + 1);
}

[Test]
public void DNET()
{
Expand All @@ -280,5 +321,24 @@ public void DNET()
}

#endregion

#region Methods

private static void GetSomething(string connectionString)
{
using (FbConnection conn = new FbConnection(connectionString))
{
conn.Open();
using (FbCommand command = new FbCommand("select current_timestamp from mon$database", conn))
{
FbConnectionStringBuilder csb = BuildConnectionStringBuilder();
csb.Pooling = true;
csb.ConnectionLifeTime = 5;
string cs = csb.ToString(); command.ExecuteScalar();
}
}
}

#endregion
}
}

0 comments on commit fbbb649

Please sign in to comment.