2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / ByteFX.Data / mysqlclient / MySqlPool.cs
index f206f8c79db0bfe4eaba2a31f3cd44afd6f27f2f..09bfdaf79fc714aed31b2bfbdaf5b71d2a25669e 100644 (file)
-using System;
-using ByteFX.Data.Common;
-using System.Collections;
-
-namespace ByteFX.Data.MySqlClient
-{
-       /// <summary>
-       /// Summary description for MySqlPool.
-       /// </summary>
-       internal sealed class MySqlPool
-       {
-               private ArrayList                       inUsePool;
-               private ArrayList                       idlePool;
-               private int                                     minSize;
-               private int                                     maxSize;
-
-               public MySqlPool(int minSize, int maxSize)
-               {
-                       this.minSize = minSize;
-                       this.maxSize = maxSize;
-                       inUsePool =new ArrayList(minSize);
-                       idlePool = new ArrayList(minSize);
-               }
-
-               private MySqlInternalConnection GetPooledConnection()
-               {
-                       lock (idlePool.SyncRoot) 
-                       {
-                               foreach (MySqlInternalConnection conn in idlePool)
-                               {
-                                       if (conn.IsAlive()) 
-                                       {
-                                               lock (inUsePool) 
-                                               {
-                                                       inUsePool.Add( conn );
-                                               }
-                                               idlePool.Remove( conn );
-                                               return conn;
-                                       }
-                                       else 
-                                       {
-                                               conn.Close();
-                                               idlePool.Remove(conn);
-                                       }
-                               }
-                       }
-                       return null;
-               }
-
-               private MySqlInternalConnection CreateNewPooledConnection( MySqlConnectionString settings )
-               {
-                       MySqlInternalConnection conn = new MySqlInternalConnection( settings );
-                       conn.Open();
-                       return conn;
-               }
-
-               public void ReleaseConnection( MySqlInternalConnection connection )
-               {
-                       lock (inUsePool.SyncRoot)
-                               lock (idlePool.SyncRoot) 
-                               {
-                                       inUsePool.Remove( connection );
-                                       if (connection.Settings.ConnectionLifetime != 0 && connection.IsTooOld())
-                                               connection.Close();
-                                       else
-                                               idlePool.Add( connection );
-                               }
-               }
-
-               public MySqlInternalConnection GetConnection(MySqlConnectionString settings) 
-               {
-                       MySqlInternalConnection conn;
-
-                       DateTime start = DateTime.Now;
-                       TimeSpan ts;
-                       do 
-                       {
-                               conn = GetPooledConnection();
-                               if (conn == null)
-                                       conn = CreateNewPooledConnection( settings );
-                               ts = DateTime.Now.Subtract( start );
-                       } while (conn == null && ts.Seconds < settings.ConnectTimeout );
-
-                                        
-                       // 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;
-                       //System.Diagnostics.Debug.WriteLine("Creating a new driver");
-/*                     Driver driver = new Driver();
-                       try 
-                       {
-                               driver.Connection = conn;
-                               driver.Open( conn.DataSource, conn.Port, conn.User, conn.Password, conn.UseCompression );
-
-                               driver.SendCommand( DBCmd.INIT_DB, connString["database"] );
-                       }
-                       catch (Exception ex)
-                       {
-                               throw new MySqlException("Database initialization failed with message: " + ex.Message);
-                       }
-
-                       pool.Add( driver );
-                       return driver;*/
-               }
-
-       }
-}
+using System;\r
+using ByteFX.Data.Common;\r
+using System.Collections;\r
+\r
+namespace ByteFX.Data.MySqlClient\r
+{\r
+       /// <summary>\r
+       /// Summary description for MySqlPool.\r
+       /// </summary>\r
+       internal sealed class MySqlPool\r
+       {\r
+               private ArrayList                               inUsePool;\r
+               private ArrayList                               idlePool;\r
+               private MySqlConnectionString   settings;\r
+               private int                                             minSize;\r
+               private int                                             maxSize;\r
+\r
+               public MySqlPool(MySqlConnectionString settings)\r
+               {\r
+                       minSize = settings.MinPoolSize;\r
+                       maxSize = settings.MaxPoolSize;\r
+                       this.settings = settings;\r
+                       inUsePool =new ArrayList();\r
+                       idlePool = new ArrayList( settings.MinPoolSize );\r
+\r
+                       // prepopulate the idle pool to minSize\r
+                       for (int i=0; i < minSize; i++) \r
+                               CreateNewPooledConnection();\r
+               }\r
+\r
+               private void CheckOutConnection(MySqlInternalConnection conn) \r
+               {\r
+               }\r
+\r
+               private MySqlInternalConnection GetPooledConnection()\r
+               {\r
+                       MySqlInternalConnection conn = null;\r
+\r
+                       // if there are no idle connections and the in use pool is full\r
+                       // then return null to indicate that we cannot provide a connection\r
+                       // at this time.\r
+                       if (idlePool.Count == 0 && inUsePool.Count == maxSize) return null;\r
+\r
+                       lock (idlePool.SyncRoot) \r
+                       {\r
+                               for (int i=idlePool.Count-1; i >=0; i--)\r
+                               {\r
+                                       conn = (idlePool[i] as MySqlInternalConnection);\r
+                                       if (conn.IsAlive()) \r
+                                       {\r
+                                               lock (inUsePool) \r
+                                               {\r
+                                                       inUsePool.Add( conn );\r
+                                               }\r
+                                               idlePool.RemoveAt( i );\r
+                                               return conn;\r
+                                       }\r
+                                       else \r
+                                       {\r
+                                               conn.Close();\r
+                                               idlePool.RemoveAt(i);\r
+                                               conn = null;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // if we couldn't get a pooled connection and there is still room\r
+                       // make a new one\r
+                       if (conn == null && (idlePool.Count+inUsePool.Count) < maxSize)\r
+                       {\r
+                               conn = CreateNewPooledConnection();\r
+                               if (conn == null) return null;\r
+\r
+                               lock (idlePool.SyncRoot)\r
+                                       lock (inUsePool.SyncRoot) \r
+                                       {\r
+                                               idlePool.Remove( conn );\r
+                                               inUsePool.Add( conn );\r
+                                       }\r
+                       }\r
+\r
+                       return conn;\r
+               }\r
+\r
+               private MySqlInternalConnection CreateNewPooledConnection()\r
+               {\r
+                       lock(idlePool.SyncRoot) \r
+                               lock (inUsePool.SyncRoot)\r
+                               {\r
+                                       // first we check if we are allowed to create another\r
+                                       if ((inUsePool.Count + idlePool.Count) == maxSize) return null;\r
+\r
+                                       MySqlInternalConnection conn = new MySqlInternalConnection( settings );\r
+                                       conn.Open();\r
+                                       idlePool.Add( conn );\r
+                                       return conn;\r
+                               }\r
+               }\r
+\r
+               public void ReleaseConnection( MySqlInternalConnection connection )\r
+               {\r
+                       lock (idlePool.SyncRoot)\r
+                               lock (inUsePool.SyncRoot) \r
+                               {\r
+                                       inUsePool.Remove( connection );\r
+                                       if (connection.Settings.ConnectionLifetime != 0 && connection.IsTooOld())\r
+                                               connection.Close();\r
+                                       else\r
+                                               idlePool.Add( connection );\r
+                               }\r
+               }\r
+\r
+               public MySqlInternalConnection GetConnection() \r
+               {\r
+                       MySqlInternalConnection conn = null;\r
+\r
+                       int start = Environment.TickCount;\r
+                       int ticks = settings.ConnectionTimeout * 1000;\r
+\r
+                       // wait timeOut seconds at most to get a connection\r
+                       while (conn == null && (Environment.TickCount - start) < ticks)\r
+                               conn = GetPooledConnection();\r
+                                        \r
+                       // if pool size is at maximum, then we must have reached our timeout so we simply\r
+                       // throw our exception\r
+                       if (conn == null)\r
+                               throw new MySqlException("error connecting: Timeout expired.  The timeout period elapsed " + \r
+                                       "prior to obtaining a connection from the pool.  This may have occurred because all " +\r
+                                       "pooled connections were in use and max pool size was reached.");\r
+\r
+                       return conn;\r
+               }\r
+\r
+       }\r
+}\r