// // System.Data.SqlClient.SqlConnectionPool.cs // // Author: // Tim Coleman (tim@timcoleman.com) // // Copyright (C) 2002 Tim Coleman // using Mono.Data.Tds.Protocol; using System; using System.Collections; using System.Threading; namespace System.Data.SqlClient { internal class SqlConnectionPool : MarshalByRefObject, IList, ICollection, IEnumerable { #region Fields ArrayList list = new ArrayList (); int maxSize; int minSize; int packetSize; int port; int timeout; string dataSource; #endregion // Fields #region Constructors public SqlConnectionPool (string dataSource, int port, int packetSize, int timeout, int minSize, int maxSize) { this.dataSource = dataSource; this.port = port; this.packetSize = packetSize; this.timeout = timeout; this.minSize = minSize; this.maxSize = maxSize; } #endregion // Constructors #region Properties public ITds this[int index] { get { return (ITds) list[index]; } } object IList.this[int index] { get { return this[index]; } set { throw new InvalidOperationException (); } } public int Count { get { return list.Count; } } public bool IsFixedSize { get { return false; } } public bool IsReadOnly { get { return true; } } public bool IsSynchronized { get { return false; } } public int MaxSize { get { return maxSize; } } public int MinSize { get { return minSize; } } public object SyncRoot { get { throw new InvalidOperationException (); } } #endregion // Properties #region Methods public int Add (object o) { return list.Add ((Tds) o); } public void Clear () { list.Clear (); } public bool Contains (object o) { return list.Contains ((Tds) o); } public void CopyTo (Array array, int index) { list.CopyTo (array, index); } public IEnumerator GetEnumerator () { return list.GetEnumerator (); } [MonoTODO ("Handle pool exhaustion.")] public ITds AllocateConnection () { // make sure we have the minimum count (really only useful the first time) lock (list) { for (int i = Count; i < minSize; i += 1) Add (new Tds70 (dataSource, port, packetSize, timeout)); } // Try to obtain a lock foreach (object o in list) if (Monitor.TryEnter (o)) return (ITds) o; if (Count < maxSize) { Tds tds = new Tds70 (dataSource, port, packetSize, timeout); Monitor.Enter (tds); Add (tds); return tds; } // else we have to wait for one to be available return null; } public void ReleaseConnection (ITds tds) { // Check if connection is still valid try { // Send dummy statement to check connection tds.Execute("select 1"); } catch { // Remove invalid connection list.Remove(tds); } finally { // Release lock Monitor.Exit (tds); } } public int IndexOf (object o) { return list.IndexOf ((Tds) o); } public void Insert (int index, object o) { list.Insert (index, (Tds) o); } public void Remove (object o) { list.Remove ((Tds) o); } public void RemoveAt (int index) { list.RemoveAt (index); } #endregion // Methods } }