2007-09-25 Nagappan A <anagappan@novell.com>
[mono.git] / mcs / class / Mono.Data.Tds / Mono.Data.Tds.Protocol / TdsConnectionPool.cs
1 //
2 // Mono.Data.TdsClient.TdsConnectionPool.cs
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // Copyright (C) 2004 Novell, Inc.
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using Mono.Data.Tds.Protocol;
32 using System;
33 using System.Collections;
34 using System.Threading;
35
36 namespace Mono.Data.Tds.Protocol 
37 {
38         public class TdsConnectionPoolManager
39         {
40                 Hashtable pools = new Hashtable ();
41                 TdsVersion version;
42                 
43                 public TdsConnectionPoolManager (TdsVersion version)
44                 {
45                         this.version = version;
46                 }
47                 
48                 public TdsConnectionPool GetConnectionPool (string connectionString, TdsConnectionInfo info)
49                 {
50                         lock (pools)
51                         {
52                                 TdsConnectionPool pool = (TdsConnectionPool) pools [connectionString];
53                                 if (pool == null) {
54                                         pool = new TdsConnectionPool (this, info);
55                                         pools [connectionString] = pool;
56                                 }
57                                 return pool;
58                         }
59                 }
60                 
61                 public Hashtable GetConnectionPool ()
62                 {
63                         lock (pools)
64                         {
65                                 return pools;
66                         }
67                 }
68                 
69                 public virtual ITds CreateConnection (TdsConnectionInfo info)
70                 {
71                         switch (version)
72                         {
73                                 case TdsVersion.tds42:
74                                         return new Tds42 (info.DataSource, info.Port, info.PacketSize, info.Timeout);
75                                 case TdsVersion.tds50:
76                                         return new Tds50 (info.DataSource, info.Port, info.PacketSize, info.Timeout);
77                                 case TdsVersion.tds70:
78                                         return new Tds70 (info.DataSource, info.Port, info.PacketSize, info.Timeout);
79                                 case TdsVersion.tds80:
80                                         return new Tds80 (info.DataSource, info.Port, info.PacketSize, info.Timeout);
81                         }
82                         throw new NotSupportedException ();
83                 }
84         }
85         
86         public class TdsConnectionInfo
87         {
88                 public TdsConnectionInfo (string dataSource, int port, int packetSize, int timeout, int minSize, int maxSize)
89                 {
90                         DataSource = dataSource;
91                         Port = port;
92                         PacketSize = packetSize;
93                         Timeout = timeout;
94                         PoolMinSize = minSize;
95                         PoolMaxSize = maxSize;
96                 }
97                 
98                 public string DataSource;
99                 public int Port;
100                 public int PacketSize;
101                 public int Timeout;
102                 public int PoolMinSize;
103                 public int PoolMaxSize;
104         }
105         
106         public class TdsConnectionPool
107         {
108                 ArrayList list = new ArrayList ();
109                 TdsConnectionInfo info;
110                 bool initialized;
111                 static bool pooling = false;
112                 int activeConnections = 0;
113                 TdsConnectionPoolManager manager;
114
115                 public TdsConnectionPool (TdsConnectionPoolManager manager, TdsConnectionInfo info)
116                 {
117                         this.info = info;
118                         this.manager = manager;
119                 }
120
121                 public static bool Pooling {
122                         get { return pooling; }
123                         set { pooling = value; }
124                 }
125
126                 #region Methods
127
128                 public ITds GetConnection ()
129                 {
130                         ITds connection = null;
131                         lock (list)
132                         {
133                                 if (!initialized) 
134                                 {
135                                         for (int n = 0; n < info.PoolMinSize; n++)
136                                                 list.Add (CreateConnection ());
137                                         initialized = true;
138                                 }
139                                 do {
140                                         if (list.Count > 0)
141                                         {
142                                                 // There are available connections
143                                                 connection = (ITds) list [list.Count - 1];
144                                                 list.RemoveAt (list.Count - 1);
145                                                 if (!connection.Reset ()) {
146                                                         try {
147                                                                 connection.Disconnect ();
148                                                         } catch {}
149                                                         connection = null;
150                                                         continue;
151                                                 }
152                                         }
153
154                                         if (connection == null && activeConnections < info.PoolMaxSize)
155                                         {
156                                                 // No connections available, but the connection limit
157                                                 // has not been reached yet, so a new one can be created
158                                                 connection = CreateConnection();
159                                         }
160
161                                         // No available connections in the pool
162                                         // Wait for somewone to release one.
163                                         if (connection == null)
164                                         {
165                                                 Monitor.Wait (list);
166                                         }
167                                 } 
168                                 while (connection == null);
169                         }
170
171                         return connection;
172                 }
173
174                 public void ReleaseConnection (ITds tds)
175                 {
176                         lock (list)
177                         {
178                                 list.Add (tds);
179                                 Monitor.Pulse (list);
180                         }
181                 }
182
183 #if NET_2_0
184                 public void ReleaseConnection (ref ITds tds)
185                 {
186                         lock (list)
187                         {
188                                 if (pooling == false) {
189                                         try {
190                                                 tds.Disconnect ();
191                                         } catch {}
192                                         tds = null;
193                                 } else {
194                                         list.Add (tds);
195                                         Monitor.Pulse (list);
196                                 }
197                         }
198                 }
199
200                 public void ResetConnectionPool ()
201                 {
202                         lock (list)
203                         {
204                                 ITds connection = null;
205                                 while (list.Count > 0) {
206                                         // There are available connections
207                                         connection = (ITds) list [list.Count - 1];
208                                         list.RemoveAt (list.Count - 1);
209                                         if (!connection.Reset ()) {
210                                                 try {
211                                                         connection.Disconnect ();
212                                                 } catch {}
213                                                 connection = null;
214                                         }
215                                 }
216                         }
217                 }
218
219                 public void ResetConnectionPool (ITds connection)
220                 {
221                         lock (list)
222                         {
223                                 if (list.Count > 0) {
224                                         // There are available connections
225                                         int index = list.IndexOf (connection);
226                                         if (index != -1) {
227                                                 list.RemoveAt (index);
228                                                 if (!connection.Reset ()) {
229                                                         try {
230                                                                 connection.Disconnect ();
231                                                         } catch {}
232                                                         connection = null;
233                                                 }
234                                         }
235                                 }
236                         }
237                 }
238 #endif
239                 
240                 ITds CreateConnection ()
241                 {
242                         activeConnections++;
243                         return manager.CreateConnection (info);
244                 }
245                 
246                 #endregion // Methods
247         }
248 }