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); }
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) { // 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.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; } else if (PoolGroupStateIdle == _state) { _state = PoolGroupStateDisabled; } } return(PoolGroupStateDisabled == _state); } }