From: Date: May 7 2008 3:47pm Subject: Connector/NET commit: r1282 - in branches/5.2: . MySql.Data/Provider MySql.Data/Provider/Source List-Archive: http://lists.mysql.com/commits/46456 X-Bug: 34001 Message-Id: <200805071347.m47Dl0FA031260@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/5.2/CHANGES branches/5.2/MySql.Data/Provider/MySql.Data.CF.csproj branches/5.2/MySql.Data/Provider/MySql.Data.csproj branches/5.2/MySql.Data/Provider/Source/MySqlPool.cs branches/5.2/MySql.Data/Provider/Source/MySqlPoolManager.cs Log: Removed some unnecessary locking from the pool manager and also reworked the pooling code to not use a semaphore (bug #34001) Modified: branches/5.2/CHANGES =================================================================== --- branches/5.2/CHANGES 2008-05-07 13:44:05 UTC (rev 1281) +++ branches/5.2/CHANGES 2008-05-07 13:47:00 UTC (rev 1282) @@ -22,6 +22,9 @@ - The procedure parameters schema collection has been altered to match what is coming with MySQL 6.0. Some fields have been removed and others combined. Please review your application for incompatibilities. +- Removed some unnecessary locking from the pool manager and also reworked the pooling + code to not use a semaphore (bug #34001) + Version 5.2.1 - 2/27/2008 - Tons of fixes in providers. The actually work now. :) Modified: branches/5.2/MySql.Data/Provider/MySql.Data.CF.csproj =================================================================== --- branches/5.2/MySql.Data/Provider/MySql.Data.CF.csproj 2008-05-07 13:44:05 UTC (rev 1281) +++ branches/5.2/MySql.Data/Provider/MySql.Data.CF.csproj 2008-05-07 13:47:00 UTC (rev 1282) @@ -63,7 +63,6 @@ - Modified: branches/5.2/MySql.Data/Provider/MySql.Data.csproj =================================================================== --- branches/5.2/MySql.Data/Provider/MySql.Data.csproj 2008-05-07 13:44:05 UTC (rev 1281) +++ branches/5.2/MySql.Data/Provider/MySql.Data.csproj 2008-05-07 13:47:00 UTC (rev 1282) @@ -221,7 +221,6 @@ - Modified: branches/5.2/MySql.Data/Provider/Source/MySqlPool.cs =================================================================== --- branches/5.2/MySql.Data/Provider/Source/MySqlPool.cs 2008-05-07 13:44:05 UTC (rev 1281) +++ branches/5.2/MySql.Data/Provider/Source/MySqlPool.cs 2008-05-07 13:47:00 UTC (rev 1282) @@ -20,12 +20,9 @@ using System; using System.Collections; -using System.Threading; using System.Collections.Generic; using System.Diagnostics; -#if CF -using MySql.Data.Common; -#endif +using System.Threading; namespace MySql.Data.MySqlClient { @@ -46,13 +43,18 @@ private uint maxSize; private ProcedureCache procedureCache; private Object lockObject; - private Semaphore poolGate; private bool beingCleared; + private int available; + private AutoResetEvent autoEvent; public MySqlPool(MySqlConnectionStringBuilder settings) { minSize = settings.MinimumPoolSize; maxSize = settings.MaximumPoolSize; + + available = (int)maxSize; + autoEvent = new AutoResetEvent(false); + if (minSize > maxSize) minSize = maxSize; this.settings = settings; @@ -69,7 +71,6 @@ idlePool.Enqueue(CreateNewPooledConnection()); procedureCache = new ProcedureCache((int)settings.ProcedureCacheSize); - poolGate = new Semaphore((int)maxSize, (int)maxSize); // we don't really need to create this but it makes the code a bit cleaner lockObject = new Object(); @@ -165,6 +166,8 @@ /// private Driver CreateNewPooledConnection() { + Debug.Assert((maxSize - NumConnections) > 0, "Pool out of sync."); + Driver driver = Driver.Create(settings); driver.Pool = this; return driver; @@ -185,9 +188,8 @@ else idlePool.Enqueue(driver); - // we now either have a connection available or have room to make - // one so we release one slot in our semaphore - poolGate.Release(); + Interlocked.Increment(ref available); + autoEvent.Set(); } } @@ -205,7 +207,8 @@ if (inUsePool.Contains(driver)) { inUsePool.Remove(driver); - poolGate.Release(); + Interlocked.Increment(ref available); + autoEvent.Set(); } // if we are being cleared and we are out of connections then have @@ -215,32 +218,45 @@ } } + private Driver TryToGetDriver() + { + int count = Interlocked.Decrement(ref available); + if (count < 0) + { + Interlocked.Increment(ref available); + return null; + } + try + { + Driver driver = GetPooledConnection(); + return driver; + } + catch (Exception ex) + { + if (settings.Logging) + Logger.LogException(ex); + Interlocked.Increment(ref available); + throw; + } + } + public Driver GetConnection() { - int ticks = (int)settings.ConnectionTimeout * 1000; + int fullTimeOut = (int)settings.ConnectionTimeout * 1000; + int timeOut = fullTimeOut; - // wait till we are allowed in - bool allowed = poolGate.WaitOne(ticks, false); - if (! allowed) - throw new MySqlException(Resources.TimeoutGettingConnection); + DateTime start = DateTime.Now; - // if we get here, then it means that we either have an idle connection - // or room to make a new connection - lock (lockObject) + while (timeOut > 0) { - try - { - Driver d = GetPooledConnection(); - return d; - } - catch (Exception ex) - { - if (settings.Logging) - Logger.LogException(ex); - poolGate.Release(); - throw; - } + Driver driver = TryToGetDriver(); + if (driver != null) return driver; + + // We have no tickets right now, lets wait for one. + if (!autoEvent.WaitOne(timeOut, false)) break; + timeOut = fullTimeOut - (int)DateTime.Now.Subtract(start).TotalMilliseconds; } + throw new MySqlException(Resources.TimeoutGettingConnection); } /// Modified: branches/5.2/MySql.Data/Provider/Source/MySqlPoolManager.cs =================================================================== --- branches/5.2/MySql.Data/Provider/Source/MySqlPoolManager.cs 2008-05-07 13:44:05 UTC (rev 1281) +++ branches/5.2/MySql.Data/Provider/Source/MySqlPoolManager.cs 2008-05-07 13:47:00 UTC (rev 1282) @@ -66,10 +66,7 @@ MySqlPool pool = driver.Pool; if (pool == null) return; - lock (pools.SyncRoot) - { - pool.RemoveConnection(driver); - } + pool.RemoveConnection(driver); } public static void ReleaseConnection(Driver driver) @@ -77,10 +74,7 @@ MySqlPool pool = driver.Pool; if (pool == null) return; - lock (pools.SyncRoot) - { - pool.ReleaseConnection(driver); - } + pool.ReleaseConnection(driver); } public static void ClearPool(MySqlConnectionStringBuilder settings)