* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.Database / MonoDevelop.Database.Sql / ConnectionPool / DefaultConnectionPool.cs
blob65027851a3b4284dbde81848545fa4bb06b5ffb2
1 //
2 // Authors:
3 // Ben Motmans <ben.motmans@gmail.com>
4 //
5 // Copyright (c) 2007 Ben Motmans
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 // THE SOFTWARE.
26 using System;
27 using System.Data;
28 using System.Collections.Generic;
30 namespace MonoDevelop.Database.Sql
32 public class DefaultConnectionPool : IConnectionPool
34 protected int minSize = 1;
35 protected int maxSize = 20;
36 protected int growSize = 3;
37 protected int shrinkSize = 5;
39 protected bool hasErrors;
40 protected string error;
42 protected IDbFactory factory;
43 protected DatabaseConnectionContext context;
44 protected IConnectionProvider connectionProvider;
46 protected bool hasVersion;
47 protected Version databaseVersion;
49 protected bool isInitialized;
51 protected List<IPooledDbConnection> connections;
52 protected Queue<IPooledDbConnection> freeConnections;
54 protected object sync = new object ();
56 public DefaultConnectionPool (IDbFactory factory, IConnectionProvider connectionProvider, DatabaseConnectionContext context)
58 if (factory == null)
59 throw new ArgumentNullException ("factory");
60 if (connectionProvider == null)
61 throw new ArgumentNullException ("connectionProvider");
62 if (context == null)
63 throw new ArgumentNullException ("context");
65 this.factory = factory;
66 this.connectionProvider = connectionProvider;
67 this.context = context;
69 connections = new List<IPooledDbConnection> ();
70 freeConnections = new Queue<IPooledDbConnection> ();
73 public virtual IDbFactory DbFactory {
74 get { return factory; }
77 public virtual DatabaseConnectionContext ConnectionContext {
78 get { return context; }
81 public virtual IConnectionProvider ConnectionProvider {
82 get { return connectionProvider; }
85 public virtual bool IsInitialized {
86 get { return isInitialized; }
89 public virtual bool HasErrors {
90 get { return hasErrors; }
93 public virtual string Error {
94 get { return error; }
97 public virtual bool HasVersion {
98 get { return hasVersion; }
101 public virtual Version DatabaseVersion {
102 get { return databaseVersion; }
105 public virtual int MinSize {
106 get { return minSize; }
107 set {
108 if (value < 1 || value > maxSize)
109 throw new IndexOutOfRangeException ("MinSize");
110 minSize = value;
114 public virtual int MaxSize {
115 get { return maxSize; }
116 set {
117 if (value < minSize)
118 throw new IndexOutOfRangeException ("MaxSize");
119 maxSize = value;
123 public virtual int GrowSize {
124 get { return growSize; }
125 set {
126 if (value < 1 || value > 10)
127 throw new IndexOutOfRangeException ("GrowSize");
128 growSize = value;
132 public virtual int ShrinkSize {
133 get { return shrinkSize; }
134 set {
135 if (value < 1 || value > 10)
136 throw new IndexOutOfRangeException ("GrowSize");
137 shrinkSize = value;
141 public virtual int ConnectionCount {
142 get {
143 lock (sync)
144 return connections.Count + freeConnections.Count;
148 public virtual int FreeConnectionCount {
149 get {
150 lock (sync)
151 return freeConnections.Count;
155 public virtual bool HasFreeConnection {
156 get {
157 lock (sync)
158 return freeConnections.Count > 0;
162 public virtual IPooledDbConnection Request ()
164 IPooledDbConnection conn = null;
165 if (HasFreeConnection) {
166 lock (sync) {
167 conn = freeConnections.Dequeue ();
168 connections.Add (conn);
170 } else {
171 if (Grow ())
172 conn = Request ();
173 else
174 conn = null;
176 return conn;
179 public virtual void Release (IPooledDbConnection connection)
181 if (connection == null)
182 return;
184 lock (sync) {
185 if (freeConnections.Contains (connection))
186 return;
188 if (connectionProvider.CheckConnection (connection, context.ConnectionSettings))
189 freeConnections.Enqueue (connection);
190 connections.Remove (connection);
192 Shrink ();
195 public virtual bool Initialize ()
197 if (isInitialized)
198 return true;
200 isInitialized = CreateNewConnections (minSize);
201 if (!isInitialized)
202 Cleanup ();
204 return isInitialized;
207 protected virtual bool CreateNewConnections (int count)
209 for (int i=0; i<count; i++) {
210 if (!CreateNewConnection ())
211 return false;
213 return true;
216 protected virtual bool CreateNewConnection ()
218 IPooledDbConnection conn = connectionProvider.CreateConnection (this, context.ConnectionSettings, out error);
219 if (conn == null || !conn.IsOpen) {
220 hasErrors = true;
221 return false;
224 if (!hasVersion) {
225 databaseVersion = conn.DatabaseVersion;
226 hasVersion = true;
229 hasErrors = false;
230 lock (sync)
231 freeConnections.Enqueue (conn);
233 return true;
236 public virtual void Close ()
238 Cleanup ();
239 isInitialized = false;
240 hasErrors = false;
241 error = null;
242 hasVersion = false;
245 protected virtual void Cleanup ()
247 lock (sync) {
248 foreach (IPooledDbConnection conn in connections)
249 conn.Dispose ();
250 foreach (IPooledDbConnection conn in freeConnections)
251 conn.Dispose ();
255 protected virtual bool Grow ()
257 return CreateNewConnections (growSize);
260 protected virtual void Shrink ()
262 if (FreeConnectionCount < shrinkSize)
263 return;
265 for (int i=0; i<shrinkSize; i++) {
266 if (HasFreeConnection) {
267 lock (sync) {
268 IPooledDbConnection conn = freeConnections.Dequeue ();
269 conn.Dispose ();