internal int Clear()
        {
            // must be multi-thread safe with competing calls by Clear and Prune via background thread
            // will return the number of connections in the group after clearing has finished

            // First, note the old collection and create a new collection to be used
            ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool> oldPoolCollection = null;

            lock (this)
            {
                if (_poolCollection.Count > 0)
                {
                    oldPoolCollection = _poolCollection;
                    _poolCollection   = new ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool>();
                }
            }

            // Then, if a new collection was created, release the pools from the old collection
            if (oldPoolCollection != null)
            {
                foreach (var entry in oldPoolCollection)
                {
                    DbConnectionPool pool = entry.Value;
                    if (pool != null)
                    {
                        DbConnectionFactory connectionFactory = pool.ConnectionFactory;
                        connectionFactory.QueuePoolForRelease(pool, true);
                    }
                }
            }

            // Finally, return the pool collection count - this may be non-zero if something was added while we were clearing
            return(_poolCollection.Count);
        }
Beispiel #2
0
        internal bool Prune()
        {
            // must only call from DbConnectionFactory.PruneConnectionPoolGroups on background timer thread
            // must lock(DbConnectionFactory._connectionPoolGroups.SyncRoot) before calling ReadyToRemove
            //     to avoid conflict with DbConnectionFactory.CreateConnectionPoolGroup replacing pool entry
            lock (this)
            {
                if (_poolCollection.Count > 0)
                {
                    var newPoolCollection = new ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool>();

                    foreach (KeyValuePair <DbConnectionPoolIdentity, DbConnectionPool> entry in _poolCollection)
                    {
                        DbConnectionPool pool = entry.Value;
                        if (pool != null)
                        {
                            // Actually prune the pool if there are no connections in the pool and no errors occurred.
                            // Empty pool during pruning indicates zero or low activity, but
                            //  an error state indicates the pool needs to stay around to
                            //  throttle new connection attempts.
                            if ((!pool.ErrorOccurred) && (0 == pool.Count))
                            {
                                // Order is important here.  First we remove the pool
                                // from the collection of pools so no one will try
                                // to use it while we're processing and finally we put the
                                // pool into a list of pools to be released when they
                                // are completely empty.
                                DbConnectionFactory connectionFactory = pool.ConnectionFactory;
#if NETFRAMEWORK
                                connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Decrement();
#endif
                                connectionFactory.QueuePoolForRelease(pool, false);
                            }
                            else
                            {
                                newPoolCollection.TryAdd(entry.Key, entry.Value);
                            }
                        }
                    }
                    _poolCollection = newPoolCollection;
                }

                // must be pruning thread to change state and no connections
                // otherwise pruning thread risks making entry disabled soon after user calls ClearPool
                if (0 == _poolCollection.Count)
                {
                    if (PoolGroupStateActive == _state)
                    {
                        _state = PoolGroupStateIdle;
                        SqlClientEventSource.Log.TryTraceEvent("<prov.DbConnectionPoolGroup.ClearInternal|RES|INFO|CPOOL> {0}, Idle", ObjectID);
                    }
                    else if (PoolGroupStateIdle == _state)
                    {
                        _state = PoolGroupStateDisabled;
                        SqlClientEventSource.Log.TryTraceEvent("<prov.DbConnectionPoolGroup.ReadyToRemove|RES|INFO|CPOOL> {0}, Disabled", ObjectID);
                    }
                }
                return(PoolGroupStateDisabled == _state);
            }
        }
        internal int Clear()
        {
            // must be multi-thread safe with competing calls by Clear and Prune via background thread
            // will return the number of connections in the group after clearing has finished

            // First, note the old collection and create a new collection to be used
            ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool> oldPoolCollection = null;

            lock (this)
            {
                if (_poolCollection.Count > 0)
                {
                    oldPoolCollection = _poolCollection;
                    _poolCollection   = new ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool>();
                }
            }

            // Then, if a new collection was created, release the pools from the old collection
            if (oldPoolCollection != null)
            {
                foreach (var entry in oldPoolCollection)
                {
                    DbConnectionPool pool = entry.Value;
                    if (pool != null)
                    {
                        // TODO: SQLBU 422890
                        //  Pruning a pool while a connection is currently attempting to connect
                        //  will cause the pool to be prematurely abandoned. The only known effect so
                        //  far is that the errorWait throttling will be reset when this occurs.
                        //  We should be able to avoid this situation by not pruning the pool if
                        //  it's _waitCount is non-zero (i.e. no connections *in* the pool, but also
                        //  no connections attempting to be created for the pool).

                        DbConnectionFactory connectionFactory = pool.ConnectionFactory;
                        connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Decrement();
                        connectionFactory.QueuePoolForRelease(pool, true);
                    }
                }
            }

            // Finally, return the pool collection count - this may be non-zero if something was added while we were clearing
            return(_poolCollection.Count);
        }
        internal bool Prune()
        {
            // must only call from DbConnectionFactory.PruneConnectionPoolGroups on background timer thread
            // must lock(DbConnectionFactory._connectionPoolGroups.SyncRoot) before calling ReadyToRemove
            //     to avoid conflict with DbConnectionFactory.CreateConnectionPoolGroup replacing pool entry
            lock (this)
            {
                if (_poolCollection.Count > 0)
                {
                    var newPoolCollection = new ConcurrentDictionary <DbConnectionPoolIdentity, DbConnectionPool>();

                    foreach (var entry in _poolCollection)
                    {
                        DbConnectionPool pool = entry.Value;
                        if (pool != null)
                        {
                            // TODO: SQLBU 422890
                            //  Pruning a pool while a connection is currently attempting to connect
                            //  will cause the pool to be prematurely abandoned. The only known effect so
                            //  far is that the errorWait throttling will be reset when this occurs.
                            //  We should be able to avoid this situation by not pruning the pool if
                            //  it's _waitCount is non-zero (i.e. no connections *in* the pool, but also
                            //  no connections attempting to be created for the pool).

                            // Actually prune the pool if there are no connections in the pool and no errors occurred.
                            // Empty pool during pruning indicates zero or low activity, but
                            //  an error state indicates the pool needs to stay around to
                            //  throttle new connection attempts.
                            if ((!pool.ErrorOccurred) && (0 == pool.Count))
                            {
                                // Order is important here.  First we remove the pool
                                // from the collection of pools so no one will try
                                // to use it while we're processing and finally we put the
                                // pool into a list of pools to be released when they
                                // are completely empty.
                                DbConnectionFactory connectionFactory = pool.ConnectionFactory;

                                connectionFactory.PerformanceCounters.NumberOfActiveConnectionPools.Decrement();
                                connectionFactory.QueuePoolForRelease(pool, false);
                            }
                            else
                            {
                                newPoolCollection.TryAdd(entry.Key, entry.Value);
                            }
                        }
                    }
                    _poolCollection = newPoolCollection;
                }

                // must be pruning thread to change state and no connections
                // otherwise pruning thread risks making entry disabled soon after user calls ClearPool
                if (0 == _poolCollection.Count)
                {
                    if (PoolGroupStateActive == _state)
                    {
                        _state = PoolGroupStateIdle;
                        Bid.Trace("<prov.DbConnectionPoolGroup.ClearInternal|RES|INFO|CPOOL> %d#, Idle\n", ObjectID);
                    }
                    else if (PoolGroupStateIdle == _state)
                    {
                        _state = PoolGroupStateDisabled;
                        Bid.Trace("<prov.DbConnectionPoolGroup.ReadyToRemove|RES|INFO|CPOOL> %d#, Disabled\n", ObjectID);
                    }
                }
                return(PoolGroupStateDisabled == _state);
            }
        }