using System; using ByteFX.Data.Common; using System.Collections; namespace ByteFX.Data.MySqlClient { /// /// Summary description for MySqlPool. /// internal sealed class MySqlPool { private ArrayList inUsePool; private ArrayList idlePool; private MySqlConnectionString settings; private int minSize; private int maxSize; public MySqlPool(MySqlConnectionString settings) { minSize = settings.MinPoolSize; maxSize = settings.MaxPoolSize; this.settings = settings; inUsePool =new ArrayList(); idlePool = new ArrayList( settings.MinPoolSize ); // prepopulate the idle pool to minSize for (int i=0; i < minSize; i++) CreateNewPooledConnection(); } private void CheckOutConnection(MySqlInternalConnection conn) { } private MySqlInternalConnection GetPooledConnection() { MySqlInternalConnection conn = null; // if there are no idle connections and the in use pool is full // then return null to indicate that we cannot provide a connection // at this time. if (idlePool.Count == 0 && inUsePool.Count == maxSize) return null; lock (idlePool.SyncRoot) { for (int i=idlePool.Count-1; i >=0; i--) { conn = (idlePool[i] as MySqlInternalConnection); if (conn.IsAlive()) { lock (inUsePool) { inUsePool.Add( conn ); } idlePool.RemoveAt( i ); return conn; } else { conn.Close(); idlePool.RemoveAt(i); } } } // if we couldn't get a pooled connection and there is still room // make a new one if (conn == null && (idlePool.Count+inUsePool.Count) < maxSize) { conn = CreateNewPooledConnection(); if (conn == null) return null; lock (idlePool.SyncRoot) lock (inUsePool.SyncRoot) { idlePool.Remove( conn ); inUsePool.Add( conn ); } } return conn; } private MySqlInternalConnection CreateNewPooledConnection() { lock(idlePool.SyncRoot) lock (inUsePool.SyncRoot) { // first we check if we are allowed to create another if ((inUsePool.Count + idlePool.Count) == maxSize) return null; MySqlInternalConnection conn = new MySqlInternalConnection( settings ); conn.Open(); idlePool.Add( conn ); return conn; } } public void ReleaseConnection( MySqlInternalConnection connection ) { lock (idlePool.SyncRoot) lock (inUsePool.SyncRoot) { inUsePool.Remove( connection ); if (connection.Settings.ConnectionLifetime != 0 && connection.IsTooOld()) connection.Close(); else idlePool.Add( connection ); } } public MySqlInternalConnection GetConnection() { MySqlInternalConnection conn = null; int start = Environment.TickCount; int ticks = settings.ConnectTimeout * 1000; // wait timeOut seconds at most to get a connection while (conn == null && (Environment.TickCount - start) < ticks) conn = GetPooledConnection(); // if pool size is at maximum, then we must have reached our timeout so we simply // throw our exception if (conn == null) throw new MySqlException("error connecting: Timeout expired. The timeout period elapsed " + "prior to obtaining a connection from the pool. This may have occurred because all " + "pooled connections were in use and max pool size was reached."); return conn; } } }