1 // Copyright (C) 2002 The Npgsql Development Team
2 // npgsql-general@gborg.postgresql.org
3 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // ------------------------------------------------------------------
22 // 0.00.0000 - 06/17/2002 - ulrich sprick - creation
25 using System.Collections;
27 using System.Threading;
31 internal class ConnectorPool
33 /// <value>Unique static instance of the connector pool
35 internal static ConnectorPool ConnectorPoolMgr = new Npgsql.ConnectorPool();
37 public ConnectorPool()
39 PooledConnectors = new Hashtable();
43 /// <value>Map of index to unused pooled connectors, avaliable to the
44 /// next RequestConnector() call.</value>
45 /// <remarks>This hasmap will be indexed by connection string.
46 /// This key will hold a list of the pooled connectors available to be used.</remarks>
47 internal Hashtable PooledConnectors;
49 /// <value>List of used, shared conncetors.</value>
50 /// <remarks>Points to the head of a double linked list</remarks>
51 private Npgsql.Connector SharedConnectors;
54 /// Cuts out a connector from the the list it is in.
56 /// <param name="Connector">The connector object to be cut out.</param>
57 /// <remarks>Shall be replaced if the lists will be based on
58 /// Collections.DictionaryBase classs </remarks>
59 internal void CutOutConnector( Npgsql.Connector Connector )
61 if ( Connector.Prev != null )
62 Connector.Prev.Next = Connector.Next;
63 if ( Connector.Next != null )
64 Connector.Next.Prev = Connector.Prev;
68 /// Inserts a connector at the head of a shared connector list.
70 /// <param name="Connector">The connctor to be inserted</param>
71 internal void InsertSharedConnector( Npgsql.Connector Connector )
73 if ( this.SharedConnectors == null ) // the list is empty
75 // make the connector the only member
76 Connector.Prev = Connector.Next = null;
78 else // the list is not empty
80 // Make the connector the new list head
81 Connector.Next = this.SharedConnectors;
82 this.SharedConnectors.Prev = Connector;
83 Connector.Prev = null;
85 // point the list to the new head
86 this.SharedConnectors = Connector;
90 /// Inserts a connector at the head of a pooled connector list.
92 /// <param name="Connector">The connctor to be inserted</param>
93 /*internal void InsertPooledConnector( Npgsql.Connector Connector )
95 if ( this.PooledConnectors == null ) // the list is empty
97 // make the connector the only member
98 Connector.Prev = Connector.Next = null;
100 else // the list is not empty
102 // Make the connector the new list head
103 Connector.Next = this.PooledConnectors;
104 this.PooledConnectors.Prev = Connector;
105 Connector.Prev = null;
107 // point the list to the new head
108 this.PooledConnectors = Connector;
112 internal Int32 GetPoolSize(String connectionString)
114 ArrayList pool = (ArrayList)PooledConnectors[connectionString];
124 /// Searches the shared and pooled connector lists for a
125 /// matching connector object or creates a new one.
127 /// <param name="ConnectString">used to connect to the
128 /// database server</param>
129 /// <param name="Shared">Allows multiple connections
130 /// on a single connector. </param>
131 /// <returns>A pooled connector object.</returns>
132 internal Npgsql.Connector RequestConnector (String connectionString,
138 ArrayList connectorPool = null;
142 // if a shared connector is requested then the
143 // Shared Connector List is searched first
145 /*for ( Connector = Npgsql.ConnectorPool.ConnectorPoolMgr.SharedConnectors;
146 Connector != null; Connector = Connector.Next )
148 if ( Connector.ConnectString == connectionString )
150 // Return the shared connector to caller
151 Connector.mShareCount++;
160 // if a shared connector could not be found or a
161 // nonshared connector is requested, then the pooled
162 // (unused) connectors are beeing searched.
165 connectorPool = (ArrayList)PooledConnectors[connectionString];
167 if (connectorPool == null)
169 connectorPool = new ArrayList();
170 PooledConnectors[connectionString] = connectorPool;
174 // Now look for an available connector.
176 Connector freeConnector = FindFreeConnector(connectorPool);
177 if (freeConnector != null)
178 return freeConnector;
180 // No suitable connector could be found, so create new one
181 // if there is room available.
183 if (connectorPool.Count < maxPoolSize)
185 connector = new Npgsql.Connector(connectionString, shared);
187 connectorPool.Add(connector);
190 // and then returned to the caller
195 // keep checking in the pool until some connector is available or
197 Int32 timeoutMilliseconds = timeout * 1000;
199 while (timeoutMilliseconds > 0)
201 Connector freeConnector2 = FindFreeConnector(connectorPool);
202 if (freeConnector2 != null)
203 return freeConnector2;
205 Thread.Sleep((timeoutMilliseconds > 900) ? 900 : timeoutMilliseconds);
206 timeoutMilliseconds -= 900;
209 throw new Exception("Timeout while getting a connection from pool.");
217 private Connector FindFreeConnector(ArrayList connectorPool)
219 foreach (Connector c in connectorPool)