I haven't checked it yet, can i send to you a coipy of the=20
CVS sources if they didn't work well i will review your patch, ok ??

Thanks for sources, but there are a few broblems :-(
First problem is that you sent us sources of the provider v2.0 and we use 
1.7.1. But this is not a big problem.
Next problem is that i still seeing bugs that we fixed in our version wich i 
sent to you:

1) We think it will be better to add locking in Count property:

                public int Count
                {
get {
                                lock (this.unlocked.SyncRoot)
                                {
                                        return this.unlocked.Count + 
this.locked.Count;
} }
                }

2) We assured that moving from locked list to unlocked and vice-verca must be 
atomicity operation. So, we propose to add the special method for this:
                #region Types
                private enum MoveType {LockedToUnlocked, UnlockedToLocked}
                #endregion

                private void MoveConnection(FbConnectionInternal connection, 
MoveType moveType)
                {
                        if (null == connection)
                                return;

                        lock (this.unlocked.SyncRoot)
                        {
                                switch (moveType)
                                {
                                        case MoveType.LockedToUnlocked:
                                                this.locked.Remove(connection);
                                                this.unlocked.Add(connection);
                                                break;
                                        case MoveType.UnlockedToLocked:
                                                
this.unlocked.Remove(connection);
                                                this.locked.Add(connection);
                                                break;
                                }
                        }
                }

and replace old code by calling new method:

        a) in CheckIn:
                from
                        this.locked.Remove(connection);
                        this.unlocked.Add(connection);
                to
                        MoveConnection(connection, MoveType.LockedToUnlocked);
        b) in GetConnection():
                from
                        if (result != null)
                        {
                                this.unlocked.Remove(result);
                                this.locked.Add(result);
                to
                        if (result != null)
                                MoveConnection(result, 
MoveType.UnlockedToLocked);

3) It will be more clear if you will move locking of GetConnection calls from 
CheckOut inside of GetConnection. So, we will have such code:
        for CheckOut:
                public FbConnectionInternal CheckOut()
                {
                        FbConnectionInternal newConnection = null;

                        lock (this.syncObject)
                        {
                                // 1. Try to get a connection from the unlocked 
connection list
                                newConnection = this.GetConnection();
                                if (newConnection != null)
                                        return newConnection;

                                // 2. Check if we have reached the max number 
of allowed connections
                                this.CheckMaxPoolSize();

                                // 3. Try to get a connection from the unlocked 
connection list
                                newConnection = this.GetConnection();
                                if (newConnection != null)
                                        return newConnection;

        for GetConnection:
                private FbConnectionInternal GetConnection()
                {
                        FbConnectionInternal result = null;
                        long check = -1;

                        lock (this.unlocked.SyncRoot)
                        {
                                FbConnectionInternal[] connections = 
(FbConnectionInternal[]) this.unlocked.ToArray(typeof(FbConnectionInternal));

for (int i = connections.Length - 1; i >= 0; i--) {
                                        if (connections[i].Verify())
                                        {
                                                if (this.lifeTime != 0)
                                                {
                                                        long now = 
DateTime.Now.Ticks;
                                                        long expire = 
connections[i].Created + this.lifeTime;

                                                        if (now >= expire)
                                                        {
                                                                if 
(this.CheckMinPoolSize())
                                                                {
                                                                        
this.unlocked.Remove(connections[i]);
                                                                        
this.Expire(connections[i]);
                                                                }
                                                        }
                                                        else
                                                        {
                                                                if (expire > 
check)
                                                                {
                                                                        check = 
expire;
                                                                        result 
= connections[i];
                                                                }
                                                        }
                                                }
                                                else
                                                {
                                                        result = connections[i];
                                                        break;
                                                }
                                        }
                                        else
                                        {
                                                
this.unlocked.Remove(connections[i]);
                                                this.Expire(connections[i]);
                                        }
                                }

4) Aslso we assured that in MaxPoolSize we should not only check for this.Count 
>= this.options.MaxPoolSize, but also we should check if existing locked 
connection was moved to unlocked:

                public bool HasUnlocked
                {
                        get { return this.unlocked.Count > 0; }                 
     
                }

                private bool CheckMinPoolSize()
                {
                        if (this.options.MinPoolSize > 0 && this.Count <= 
this.options.MinPoolSize)
                        {
                                return false;
                        }
                        else
                        {
                                return true;
                        }
                }

                private void CheckMaxPoolSize()
                {
                        if (this.options.MaxPoolSize > 0 && this.Count >= 
this.options.MaxPoolSize)
                        {
                                long timeout = this.options.ConnectionTimeout * 
TimeSpan.TicksPerSecond;
                                long start = DateTime.Now.Ticks;

/* Loop brakes without errors in next situations: 1. connection was returned from locked to unlocked by calling CheckIn in other thread (HasUnlocked = true) 2. connection was moved from locked to unlocked (by Checkin) and then cleaned (removed from unlocked by Cleanup)
                                */
                                while (true)
                                {
                                        if (this.Count >= this.options.MaxPoolSize 
&& this.HasUnlocked == false)
                                        {
                                                if ((DateTime.Now.Ticks - start) 
> timeout)
                                                        throw new 
SystemException("Timeout exceeded.");

                                                Thread.Sleep(100);
                                        }
                                        else
                                                break;
                                }
                        }
                }


All this changes you can find in version wich we sent to you.


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
Firebird-net-provider mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider

Reply via email to