    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.pool2.impl;
    018
    019import java.util.ArrayList;
    020import java.util.Deque;
    021import java.util.HashMap;
    022import java.util.Iterator;
    023import java.util.List;
    024import java.util.Map;
    025import java.util.Map.Entry;
    026import java.util.NoSuchElementException;
    027import java.util.TreeMap;
    028import java.util.concurrent.ConcurrentHashMap;
    029import java.util.concurrent.TimeUnit;
    030import java.util.concurrent.atomic.AtomicInteger;
    031import java.util.concurrent.atomic.AtomicLong;
    032import java.util.concurrent.locks.Lock;
    033import java.util.concurrent.locks.ReadWriteLock;
    034import java.util.concurrent.locks.ReentrantReadWriteLock;
    035
    036import org.apache.commons.pool2.KeyedObjectPool;
    037import org.apache.commons.pool2.KeyedPooledObjectFactory;
    038import org.apache.commons.pool2.PoolUtils;
    039import org.apache.commons.pool2.PooledObject;
    040import org.apache.commons.pool2.PooledObjectState;
    041import org.apache.commons.pool2.SwallowedExceptionListener;
    042
    043/**
    044 * A configurable <code>KeyedObjectPool</code> implementation.
    045 * <p>
    046 * When coupled with the appropriate {@link KeyedPooledObjectFactory},
    047 * <code>GenericKeyedObjectPool</code> provides robust pooling functionality for
    048 * keyed objects. A <code>GenericKeyedObjectPool</code> can be viewed as a map
    049 * of sub-pools, keyed on the (unique) key values provided to the
    050 * {@link #preparePool preparePool}, {@link #addObject addObject} or
    051 * {@link #borrowObject borrowObject} methods. Each time a new key value is
    052 * provided to one of these methods, a sub-new pool is created under the given
    053 * key to be managed by the containing <code>GenericKeyedObjectPool.</code>
    054 * <p>
    055 * Note that the current implementation uses a ConcurrentHashMap which uses
    056 * equals() to compare keys.
    057 * This means that distinct instance keys must be distinguishable using equals.
    058 * <p>
    059 * Optionally, one may configure the pool to examine and possibly evict objects
    060 * as they sit idle in the pool and to ensure that a minimum number of idle
    061 * objects is maintained for each key. This is performed by an "idle object
    062 * eviction" thread, which runs asynchronously. Caution should be used when
    063 * configuring this optional feature. Eviction runs contend with client threads
    064 * for access to objects in the pool, so if they run too frequently performance
    065 * issues may result.
    066 * <p>
    067 * Implementation note: To prevent possible deadlocks, care has been taken to
    068 * ensure that no call to a factory method will occur within a synchronization
    069 * block. See POOL-125 and DBCP-44 for more information.
    070 * <p>
    071 * This class is intended to be thread-safe.
    072 *
    073 * @see GenericObjectPool
    074 *
    075 * @param <K> The type of keys maintained by this pool.
    076 * @param <T> Type of element pooled in this pool.
    077 *
    078 * @since 2.0
    079 */
    080public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T>
    081        implements KeyedObjectPool<K, T>, GenericKeyedObjectPoolMXBean<K> {
    082
    083    /**
    084     * Create a new <code>GenericKeyedObjectPool</code> using defaults from
    085     * {@link GenericKeyedObjectPoolConfig}.
    086     * @param factory the factory to be used to create entries
    087     */
    088    public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K,T> factory) {
    089        this(factory, new GenericKeyedObjectPoolConfig<T>());
    090    }
    091
    092    /**
    093     * Create a new <code>GenericKeyedObjectPool</code> using a specific
    094     * configuration.
    095     *
    096     * @param factory the factory to be used to create entries
    097     * @param config    The configuration to use for this pool instance. The
    098     *                  configuration is used by value. Subsequent changes to
    099     *                  the configuration object will not be reflected in the
    100     *                  pool.
    101     */
    102    public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K, T> factory,
    103            final GenericKeyedObjectPoolConfig<T> config) {
    104
    105        super(config, ONAME_BASE, config.getJmxNamePrefix());
    106
    107        if (factory == null) {
    108            jmxUnregister(); // tidy up
    109            throw new IllegalArgumentException("factory may not be null");
    110        }
    111        this.factory = factory;
    112        this.fairness = config.getFairness();
    113
    114        setConfig(config);
    115    }
    116
    117    /**
    118     * Returns the limit on the number of object instances allocated by the pool
    119     * (checked out or idle), per key. When the limit is reached, the sub-pool
    120     * is said to be exhausted. A negative value indicates no limit.
    121     *
    122     * @return the limit on the number of active instances per key
    123     *
    124     * @see #setMaxTotalPerKey
    125     */
    126    @Override
    127    public int getMaxTotalPerKey() {
    128        return maxTotalPerKey;
    129    }
    130
    131    /**
    132     * Sets the limit on the number of object instances allocated by the pool
    133     * (checked out or idle), per key. When the limit is reached, the sub-pool
    134     * is said to be exhausted. A negative value indicates no limit.
    135     *
    136     * @param maxTotalPerKey the limit on the number of active instances per key
    137     *
    138     * @see #getMaxTotalPerKey
    139     */
    140    public void setMaxTotalPerKey(final int maxTotalPerKey) {
    141        this.maxTotalPerKey = maxTotalPerKey;
    142    }
    143
    144
    145    /**
    146     * Returns the cap on the number of "idle" instances per key in the pool.
    147     * If maxIdlePerKey is set too low on heavily loaded systems it is possible
    148     * you will see objects being destroyed and almost immediately new objects
    149     * being created. This is a result of the active threads momentarily
    150     * returning objects faster than they are requesting them, causing the
    151     * number of idle objects to rise above maxIdlePerKey. The best value for
    152     * maxIdlePerKey for heavily loaded system will vary but the default is a
    153     * good starting point.
    154     *
    155     * @return the maximum number of "idle" instances that can be held in a
    156     *         given keyed sub-pool or a negative value if there is no limit
    157     *
    158     * @see #setMaxIdlePerKey
    159     */
    160    @Override
    161    public int getMaxIdlePerKey() {
    162        return maxIdlePerKey;
    163    }
    164
    165    /**
    166     * Sets the cap on the number of "idle" instances per key in the pool.
    167     * If maxIdlePerKey is set too low on heavily loaded systems it is possible
    168     * you will see objects being destroyed and almost immediately new objects
    169     * being created. This is a result of the active threads momentarily
    170     * returning objects faster than they are requesting them, causing the
    171     * number of idle objects to rise above maxIdlePerKey. The best value for
    172     * maxIdlePerKey for heavily loaded system will vary but the default is a
    173     * good starting point.
    174     *
    175     * @param maxIdlePerKey the maximum number of "idle" instances that can be
    176     *                      held in a given keyed sub-pool. Use a negative value
    177     *                      for no limit
    178     *
    179     * @see #getMaxIdlePerKey
    180     */
    181    public void setMaxIdlePerKey(final int maxIdlePerKey) {
    182        this.maxIdlePerKey = maxIdlePerKey;
    183    }
    184
    185    /**
    186     * Sets the target for the minimum number of idle objects to maintain in
    187     * each of the keyed sub-pools. This setting only has an effect if it is
    188     * positive and {@link #getTimeBetweenEvictionRunsMillis()} is greater than
    189     * zero. If this is the case, an attempt is made to ensure that each
    190     * sub-pool has the required minimum number of instances during idle object
    191     * eviction runs.
    192     * <p>
    193     * If the configured value of minIdlePerKey is greater than the configured
    194     * value for maxIdlePerKey then the value of maxIdlePerKey will be used
    195     * instead.
    196     *
    197     * @param minIdlePerKey The minimum size of the each keyed pool
    198     *
    199     * @see #getMinIdlePerKey
    200     * @see #getMaxIdlePerKey()
    201     * @see #setTimeBetweenEvictionRunsMillis
    202     */
    203    public void setMinIdlePerKey(final int minIdlePerKey) {
    204        this.minIdlePerKey = minIdlePerKey;
    205    }
    206
    207    /**
    208     * Returns the target for the minimum number of idle objects to maintain in
    209     * each of the keyed sub-pools. This setting only has an effect if it is
    210     * positive and {@link #getTimeBetweenEvictionRunsMillis()} is greater than
    211     * zero. If this is the case, an attempt is made to ensure that each
    212     * sub-pool has the required minimum number of instances during idle object
    213     * eviction runs.
    214     * <p>
    215     * If the configured value of minIdlePerKey is greater than the configured
    216     * value for maxIdlePerKey then the value of maxIdlePerKey will be used
    217     * instead.
    218     *
    219     * @return minimum size of the each keyed pool
    220     *
    221     * @see #setTimeBetweenEvictionRunsMillis
    222     */
    223    @Override
    224    public int getMinIdlePerKey() {
    225        final int maxIdlePerKeySave = getMaxIdlePerKey();
    226        if (this.minIdlePerKey > maxIdlePerKeySave) {
    227            return maxIdlePerKeySave;
    228        }
    229        return minIdlePerKey;
    230    }
    231
    232    /**
    233     * Sets the configuration.
    234     *
    235     * @param conf the new configuration to use. This is used by value.
    236     *
    237     * @see GenericKeyedObjectPoolConfig
    238     */
    239    public void setConfig(final GenericKeyedObjectPoolConfig<T> conf) {
    240        setLifo(conf.getLifo());
    241        setMaxIdlePerKey(conf.getMaxIdlePerKey());
    242        setMaxTotalPerKey(conf.getMaxTotalPerKey());
    243        setMaxTotal(conf.getMaxTotal());
    244        setMinIdlePerKey(conf.getMinIdlePerKey());
    245        setMaxWaitMillis(conf.getMaxWaitMillis());
    246        setBlockWhenExhausted(conf.getBlockWhenExhausted());
    247        setTestOnCreate(conf.getTestOnCreate());
    248        setTestOnBorrow(conf.getTestOnBorrow());
    249        setTestOnReturn(conf.getTestOnReturn());
    250        setTestWhileIdle(conf.getTestWhileIdle());
    251        setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun());
    252        setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis());
    253        setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis());
    254        setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis());
    255        final EvictionPolicy<T> policy = conf.getEvictionPolicy();
    256        if (policy == null) {
    257            // Use the class name (pre-2.6.0 compatible)
    258            setEvictionPolicyClassName(conf.getEvictionPolicyClassName());
    259        } else {
    260            // Otherwise, use the class (2.6.0 feature)
    261            setEvictionPolicy(policy);
    262        }
    263        setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis());
    264    }
    265
    266    /**
    267     * Obtain a reference to the factory used to create, destroy and validate
    268     * the objects used by this pool.
    269     *
    270     * @return the factory
    271     */
    272    public KeyedPooledObjectFactory<K, T> getFactory() {
    273        return factory;
    274    }
    275
    276    /**
    277     * Equivalent to <code>{@link #borrowObject(Object, long) borrowObject}(key,
    278     * {@link #getMaxWaitMillis()})</code>.
    279     * <p>
    280     * {@inheritDoc}
    281     */
    282    @Override
    283    public T borrowObject(final K key) throws Exception {
    284        return borrowObject(key, getMaxWaitMillis());
    285    }
    286
    287    /**
    288     * Borrows an object from the sub-pool associated with the given key using
    289     * the specified waiting time which only applies if
    290     * {@link #getBlockWhenExhausted()} is true.
    291     * <p>
    292     * If there is one or more idle instances available in the sub-pool
    293     * associated with the given key, then an idle instance will be selected
    294     * based on the value of {@link #getLifo()}, activated and returned.  If
    295     * activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set to
    296     * <code>true</code> and validation fails, the instance is destroyed and the
    297     * next available instance is examined.  This continues until either a valid
    298     * instance is returned or there are no more idle instances available.
    299     * <p>
    300     * If there are no idle instances available in the sub-pool associated with
    301     * the given key, behavior depends on the {@link #getMaxTotalPerKey()
    302     * maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable)
    303     * {@link #getBlockWhenExhausted()} and the value passed in to the
    304     * <code>borrowMaxWaitMillis</code> parameter. If the number of instances checked
    305     * out from the sub-pool under the given key is less than
    306     * <code>maxTotalPerKey</code> and the total number of instances in
    307     * circulation (under all keys) is less than <code>maxTotal</code>, a new
    308     * instance is created, activated and (if applicable) validated and returned
    309     * to the caller. If validation fails, a <code>NoSuchElementException</code>
    310     * will be thrown.
    311     * <p>
    312     * If the associated sub-pool is exhausted (no available idle instances and
    313     * no capacity to create new ones), this method will either block
    314     * ({@link #getBlockWhenExhausted()} is true) or throw a
    315     * <code>NoSuchElementException</code>
    316     * ({@link #getBlockWhenExhausted()} is false).
    317     * The length of time that this method will block when
    318     * {@link #getBlockWhenExhausted()} is true is determined by the value
    319     * passed in to the <code>borrowMaxWait</code> parameter.
    320     * <p>
    321     * When <code>maxTotal</code> is set to a positive value and this method is
    322     * invoked when at the limit with no idle instances available under the requested
    323     * key, an attempt is made to create room by clearing the oldest 15% of the
    324     * elements from the keyed sub-pools.
    325     * <p>
    326     * When the pool is exhausted, multiple calling threads may be
    327     * simultaneously blocked waiting for instances to become available. A
    328     * "fairness" algorithm has been implemented to ensure that threads receive
    329     * available instances in request arrival order.
    330     *
    331     * @param key pool key
    332     * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
    333     *                            to become available
    334     *
    335     * @return object instance from the keyed pool
    336     *
    337     * @throws NoSuchElementException if a keyed object instance cannot be
    338     *                                returned because the pool is exhausted.
    339     *
    340     * @throws Exception if a keyed object instance cannot be returned due to an
    341     *                   error
    342     */
    343    public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception {
    344        assertOpen();
    345
    346        PooledObject<T> p = null;
    347
    348        // Get local copy of current config so it is consistent for entire
    349        // method execution
    350        final boolean blockWhenExhausted = getBlockWhenExhausted();
    351
    352        boolean create;
    353        final long waitTime = System.currentTimeMillis();
    354        final ObjectDeque<T> objectDeque = register(key);
    355
    356        try {
    357            while (p == null) {
    358                create = false;
    359                p = objectDeque.getIdleObjects().pollFirst();
    360                if (p == null) {
    361                    p = create(key);
    362                    if (p != null) {
    363                        create = true;
    364                    }
    365                }
    366                if (blockWhenExhausted) {
    367                    if (p == null) {
    368                        if (borrowMaxWaitMillis < 0) {
    369                            p = objectDeque.getIdleObjects().takeFirst();
    370                        } else {
    371                            p = objectDeque.getIdleObjects().pollFirst(
    372                                    borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
    373                        }
    374                    }
    375                    if (p == null) {
    376                        throw new NoSuchElementException(
    377                                "Timeout waiting for idle object");
    378                    }
    379                } else {
    380                    if (p == null) {
    381                        throw new NoSuchElementException("Pool exhausted");
    382                    }
    383                }
    384                if (!p.allocate()) {
    385                    p = null;
    386                }
    387
    388                if (p != null) {
    389                    try {
    390                        factory.activateObject(key, p);
    391                    } catch (final Exception e) {
    392                        try {
    393                            destroy(key, p, true);
    394                        } catch (final Exception e1) {
    395                            // Ignore - activation failure is more important
    396                        }
    397                        p = null;
    398                        if (create) {
    399                            final NoSuchElementException nsee = new NoSuchElementException(
    400                                    "Unable to activate object");
    401                            nsee.initCause(e);
    402                            throw nsee;
    403                        }
    404                    }
    405                    if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
    406                        boolean validate = false;
    407                        Throwable validationThrowable = null;
    408                        try {
    409                            validate = factory.validateObject(key, p);
    410                        } catch (final Throwable t) {
    411                            PoolUtils.checkRethrow(t);
    412                            validationThrowable = t;
    413                        }
    414                        if (!validate) {
    415                            try {
    416                                destroy(key, p, true);
    417                                destroyedByBorrowValidationCount.incrementAndGet();
    418                            } catch (final Exception e) {
    419                                // Ignore - validation failure is more important
    420                            }
    421                            p = null;
    422                            if (create) {
    423                                final NoSuchElementException nsee = new NoSuchElementException(
    424                                        "Unable to validate object");
    425                                nsee.initCause(validationThrowable);
    426                                throw nsee;
    427                            }
    428                        }
    429                    }
    430                }
    431            }
    432        } finally {
    433            deregister(key);
    434        }
    435
    436        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
    437
    438        return p.getObject();
    439    }
    440
    441
    442    /**
    443     * Returns an object to a keyed sub-pool.
    444     * <p>
    445     * If {@link #getMaxIdlePerKey() maxIdle} is set to a positive value and the
    446     * number of idle instances under the given key has reached this value, the
    447     * returning instance is destroyed.
    448     * <p>
    449     * If {@link #getTestOnReturn() testOnReturn} == true, the returning
    450     * instance is validated before being returned to the idle instance sub-pool
    451     * under the given key. In this case, if validation fails, the instance is
    452     * destroyed.
    453     * <p>
    454     * Exceptions encountered destroying objects for any reason are swallowed
    455     * but notified via a {@link SwallowedExceptionListener}.
    456     *
    457     * @param key pool key
    458     * @param obj instance to return to the keyed pool
    459     *
    460     * @throws IllegalStateException if an object is returned to the pool that
    461     *                               was not borrowed from it or if an object is
    462     *                               returned to the pool multiple times
    463     */
    464    @Override
    465    public void returnObject(final K key, final T obj) {
    466
    467        final ObjectDeque<T> objectDeque = poolMap.get(key);
    468
    469        final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
    470
    471        if (p == null) {
    472            throw new IllegalStateException(
    473                    "Returned object not currently part of this pool");
    474        }
    475
    476        markReturningState(p);
    477
    478        final long activeTime = p.getActiveTimeMillis();
    479
    480        try {
    481            if (getTestOnReturn() && !factory.validateObject(key, p)) {
    482                try {
    483                    destroy(key, p, true);
    484                } catch (final Exception e) {
    485                    swallowException(e);
    486                }
    487                whenWaitersAddObject(key, objectDeque.idleObjects);
    488                return;
    489            }
    490
    491            try {
    492                factory.passivateObject(key, p);
    493            } catch (final Exception e1) {
    494                swallowException(e1);
    495                try {
    496                    destroy(key, p, true);
    497                } catch (final Exception e) {
    498                    swallowException(e);
    499                }
    500                whenWaitersAddObject(key, objectDeque.idleObjects);
    501                return;
    502            }
    503
    504            if (!p.deallocate()) {
    505                throw new IllegalStateException(
    506                        "Object has already been returned to this pool");
    507            }
    508
    509            final int maxIdle = getMaxIdlePerKey();
    510            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
    511                    objectDeque.getIdleObjects();
    512
    513            if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
    514                try {
    515                    destroy(key, p, true);
    516                } catch (final Exception e) {
    517                    swallowException(e);
    518                }
    519            } else {
    520                if (getLifo()) {
    521                    idleObjects.addFirst(p);
    522                } else {
    523                    idleObjects.addLast(p);
    524                }
    525                if (isClosed()) {
    526                    // Pool closed while object was being added to idle objects.
    527                    // Make sure the returned object is destroyed rather than left
    528                    // in the idle object pool (which would effectively be a leak)
    529                    clear(key);
    530                }
    531            }
    532        } finally {
    533            if (hasBorrowWaiters()) {
    534                reuseCapacity();
    535            }
    536            updateStatsReturn(activeTime);
    537        }
    538    }
    539
    540    /**
    541     * Whether there is at least one thread waiting on this deque, add an pool object.
    542     * @param key
    543     * @param idleObjects
    544     */
    545    private void whenWaitersAddObject(final K key, final LinkedBlockingDeque<PooledObject<T>> idleObjects) {
    546        if (idleObjects.hasTakeWaiters()) {
    547            try {
    548                addObject(key);
    549            } catch (final Exception e) {
    550                swallowException(e);
    551            }
    552        }
    553    }
    554
    555    /**
    556     * {@inheritDoc}
    557     * <p>
    558     * Activation of this method decrements the active count associated with
    559     * the given keyed pool and attempts to destroy <code>obj.</code>
    560     *
    561     * @param key pool key
    562     * @param obj instance to invalidate
    563     *
    564     * @throws Exception             if an exception occurs destroying the
    565     *                               object
    566     * @throws IllegalStateException if obj does not belong to the pool
    567     *                               under the given key
    568     */
    569    @Override
    570    public void invalidateObject(final K key, final T obj) throws Exception {
    571
    572        final ObjectDeque<T> objectDeque = poolMap.get(key);
    573
    574        final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
    575        if (p == null) {
    576            throw new IllegalStateException(
    577                    "Object not currently part of this pool");
    578        }
    579        synchronized (p) {
    580            if (p.getState() != PooledObjectState.INVALID) {
    581                destroy(key, p, true);
    582            }
    583        }
    584        if (objectDeque.idleObjects.hasTakeWaiters()) {
    585            addObject(key);
    586        }
    587    }
    588
    589
    590    /**
    591     * Clears any objects sitting idle in the pool by removing them from the
    592     * idle instance sub-pools and then invoking the configured
    593     * PoolableObjectFactory's
    594     * {@link KeyedPooledObjectFactory#destroyObject(Object, PooledObject)}
    595     * method on each idle instance.
    596     * <p>
    597     * Implementation notes:
    598     * <ul>
    599     * <li>This method does not destroy or effect in any way instances that are
    600     * checked out when it is invoked.</li>
    601     * <li>Invoking this method does not prevent objects being returned to the
    602     * idle instance pool, even during its execution. Additional instances may
    603     * be returned while removed items are being destroyed.</li>
    604     * <li>Exceptions encountered destroying idle instances are swallowed
    605     * but notified via a {@link SwallowedExceptionListener}.</li>
    606     * </ul>
    607     */
    608    @Override
    609    public void clear() {
    610        final Iterator<K> iter = poolMap.keySet().iterator();
    611
    612        while (iter.hasNext()) {
    613            clear(iter.next());
    614        }
    615    }
    616
    617
    618    /**
    619     * Clears the specified sub-pool, removing all pooled instances
    620     * corresponding to the given <code>key</code>. Exceptions encountered
    621     * destroying idle instances are swallowed but notified via a
    622     * {@link SwallowedExceptionListener}.
    623     *
    624     * @param key the key to clear
    625     */
    626    @Override
    627    public void clear(final K key) {
    628
    629        final ObjectDeque<T> objectDeque = register(key);
    630
    631        try {
    632            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
    633                    objectDeque.getIdleObjects();
    634
    635            PooledObject<T> p = idleObjects.poll();
    636
    637            while (p != null) {
    638                try {
    639                    destroy(key, p, true);
    640                } catch (final Exception e) {
    641                    swallowException(e);
    642                }
    643                p = idleObjects.poll();
    644            }
    645        } finally {
    646            deregister(key);
    647        }
    648    }
    649
    650
    651    @Override
    652    public int getNumActive() {
    653        return numTotal.get() - getNumIdle();
    654    }
    655
    656
    657    @Override
    658    public int getNumIdle() {
    659        final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
    660        int result = 0;
    661
    662        while (iter.hasNext()) {
    663            result += iter.next().getIdleObjects().size();
    664        }
    665
    666        return result;
    667    }
    668
    669
    670    @Override
    671    public int getNumActive(final K key) {
    672        final ObjectDeque<T> objectDeque = poolMap.get(key);
    673        if (objectDeque != null) {
    674            return objectDeque.getAllObjects().size() -
    675                    objectDeque.getIdleObjects().size();
    676        }
    677        return 0;
    678    }
    679
    680
    681    @Override
    682    public int getNumIdle(final K key) {
    683        final ObjectDeque<T> objectDeque = poolMap.get(key);
    684        return objectDeque != null ? objectDeque.getIdleObjects().size() : 0;
    685    }
    686
    687
    688    /**
    689     * Closes the keyed object pool. Once the pool is closed,
    690     * {@link #borrowObject(Object)} will fail with IllegalStateException, but
    691     * {@link #returnObject(Object, Object)} and
    692     * {@link #invalidateObject(Object, Object)} will continue to work, with
    693     * returned objects destroyed on return.
    694     * <p>
    695     * Destroys idle instances in the pool by invoking {@link #clear()}.
    696     */
    697    @Override
    698    public void close() {
    699        if (isClosed()) {
    700            return;
    701        }
    702
    703        synchronized (closeLock) {
    704            if (isClosed()) {
    705                return;
    706            }
    707
    708            // Stop the evictor before the pool is closed since evict() calls
    709            // assertOpen()
    710            startEvictor(-1L);
    711
    712            closed = true;
    713            // This clear removes any idle objects
    714            clear();
    715
    716            jmxUnregister();
    717
    718            // Release any threads that were waiting for an object
    719            final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
    720            while (iter.hasNext()) {
    721                iter.next().getIdleObjects().interuptTakeWaiters();
    722            }
    723            // This clear cleans up the keys now any waiting threads have been
    724            // interrupted
    725            clear();
    726        }
    727    }
    728
    729
    730    /**
    731     * Clears oldest 15% of objects in pool.  The method sorts the objects into
    732     * a TreeMap and then iterates the first 15% for removal.
    733     */
    734    public void clearOldest() {
    735
    736        // build sorted map of idle objects
    737        final Map<PooledObject<T>, K> map = new TreeMap<>();
    738
    739        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
    740            final K k = entry.getKey();
    741            final ObjectDeque<T> deque = entry.getValue();
    742            // Protect against possible NPE if key has been removed in another
    743            // thread. Not worth locking the keys while this loop completes.
    744            if (deque != null) {
    745                final LinkedBlockingDeque<PooledObject<T>> idleObjects =
    746                        deque.getIdleObjects();
    747                for (final PooledObject<T> p : idleObjects) {
    748                    // each item into the map using the PooledObject object as the
    749                    // key. It then gets sorted based on the idle time
    750                    map.put(p, k);
    751                }
    752            }
    753        }
    754
    755        // Now iterate created map and kill the first 15% plus one to account
    756        // for zero
    757        int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
    758        final Iterator<Map.Entry<PooledObject<T>, K>> iter =
    759                map.entrySet().iterator();
    760
    761        while (iter.hasNext() && itemsToRemove > 0) {
    762            final Map.Entry<PooledObject<T>, K> entry = iter.next();
    763            // kind of backwards on naming.  In the map, each key is the
    764            // PooledObject because it has the ordering with the timestamp
    765            // value.  Each value that the key references is the key of the
    766            // list it belongs to.
    767            final K key = entry.getValue();
    768            final PooledObject<T> p = entry.getKey();
    769            // Assume the destruction succeeds
    770            boolean destroyed = true;
    771            try {
    772                destroyed = destroy(key, p, false);
    773            } catch (final Exception e) {
    774                swallowException(e);
    775            }
    776            if (destroyed) {
    777                itemsToRemove--;
    778            }
    779        }
    780    }
    781
    782    /**
    783     * Attempt to create one new instance to serve from the most heavily
    784     * loaded pool that can add a new instance.
    785     *
    786     * This method exists to ensure liveness in the pool when threads are
    787     * parked waiting and capacity to create instances under the requested keys
    788     * subsequently becomes available.
    789     *
    790     * This method is not guaranteed to create an instance and its selection
    791     * of the most loaded pool that can create an instance may not always be
    792     * correct, since it does not lock the pool and instances may be created,
    793     * borrowed, returned or destroyed by other threads while it is executing.
    794     */
    795    private void reuseCapacity() {
    796        final int maxTotalPerKeySave = getMaxTotalPerKey();
    797
    798        // Find the most loaded pool that could take a new instance
    799        int maxQueueLength = 0;
    800        LinkedBlockingDeque<PooledObject<T>> mostLoaded = null;
    801        K loadedKey = null;
    802        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
    803            final K k = entry.getKey();
    804            final ObjectDeque<T> deque = entry.getValue();
    805            if (deque != null) {
    806                final LinkedBlockingDeque<PooledObject<T>> pool = deque.getIdleObjects();
    807                final int queueLength = pool.getTakeQueueLength();
    808                if (getNumActive(k) < maxTotalPerKeySave && queueLength > maxQueueLength) {
    809                    maxQueueLength = queueLength;
    810                    mostLoaded = pool;
    811                    loadedKey = k;
    812                }
    813            }
    814        }
    815
    816        // Attempt to add an instance to the most loaded pool
    817        if (mostLoaded != null) {
    818            register(loadedKey);
    819            try {
    820                final PooledObject<T> p = create(loadedKey);
    821                if (p != null) {
    822                    addIdleObject(loadedKey, p);
    823                }
    824            } catch (final Exception e) {
    825                swallowException(e);
    826            } finally {
    827                deregister(loadedKey);
    828            }
    829        }
    830    }
    831
    832    /**
    833     * Checks to see if there are any threads currently waiting to borrow
    834     * objects but are blocked waiting for more objects to become available.
    835     *
    836     * @return {@code true} if there is at least one thread waiting otherwise
    837     *         {@code false}
    838     */
    839    private boolean hasBorrowWaiters() {
    840        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
    841            final ObjectDeque<T> deque = entry.getValue();
    842            if (deque != null) {
    843                final LinkedBlockingDeque<PooledObject<T>> pool =
    844                        deque.getIdleObjects();
    845                if(pool.hasTakeWaiters()) {
    846                    return true;
    847                }
    848            }
    849        }
    850        return false;
    851    }
    852
    853
    854    /**
    855     * {@inheritDoc}
    856     * <p>
    857     * Successive activations of this method examine objects in keyed sub-pools
    858     * in sequence, cycling through the keys and examining objects in
    859     * oldest-to-youngest order within the keyed sub-pools.
    860     */
    861    @Override
    862    public void evict() throws Exception {
    863        assertOpen();
    864
    865        if (getNumIdle() == 0) {
    866            return;
    867        }
    868
    869        PooledObject<T> underTest = null;
    870        final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
    871
    872        synchronized (evictionLock) {
    873            final EvictionConfig evictionConfig = new EvictionConfig(
    874                    getMinEvictableIdleTimeMillis(),
    875                    getSoftMinEvictableIdleTimeMillis(),
    876                    getMinIdlePerKey());
    877
    878            final boolean testWhileIdle = getTestWhileIdle();
    879
    880            for (int i = 0, m = getNumTests(); i < m; i++) {
    881                if(evictionIterator == null || !evictionIterator.hasNext()) {
    882                    if (evictionKeyIterator == null ||
    883                            !evictionKeyIterator.hasNext()) {
    884                        final List<K> keyCopy = new ArrayList<>();
    885                        final Lock readLock = keyLock.readLock();
    886                        readLock.lock();
    887                        try {
    888                            keyCopy.addAll(poolKeyList);
    889                        } finally {
    890                            readLock.unlock();
    891                        }
    892                        evictionKeyIterator = keyCopy.iterator();
    893                    }
    894                    while (evictionKeyIterator.hasNext()) {
    895                        evictionKey = evictionKeyIterator.next();
    896                        final ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
    897                        if (objectDeque == null) {
    898                            continue;
    899                        }
    900
    901                        final Deque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
    902                        evictionIterator = new EvictionIterator(idleObjects);
    903                        if (evictionIterator.hasNext()) {
    904                            break;
    905                        }
    906                        evictionIterator = null;
    907                    }
    908                }
    909                if (evictionIterator == null) {
    910                    // Pools exhausted
    911                    return;
    912                }
    913                final Deque<PooledObject<T>> idleObjects;
    914                try {
    915                    underTest = evictionIterator.next();
    916                    idleObjects = evictionIterator.getIdleObjects();
    917                } catch (final NoSuchElementException nsee) {
    918                    // Object was borrowed in another thread
    919                    // Don't count this as an eviction test so reduce i;
    920                    i--;
    921                    evictionIterator = null;
    922                    continue;
    923                }
    924
    925                if (!underTest.startEvictionTest()) {
    926                    // Object was borrowed in another thread
    927                    // Don't count this as an eviction test so reduce i;
    928                    i--;
    929                    continue;
    930                }
    931
    932                // User provided eviction policy could throw all sorts of
    933                // crazy exceptions. Protect against such an exception
    934                // killing the eviction thread.
    935                boolean evict;
    936                try {
    937                    evict = evictionPolicy.evict(evictionConfig, underTest,
    938                            poolMap.get(evictionKey).getIdleObjects().size());
    939                } catch (final Throwable t) {
    940                    // Slightly convoluted as SwallowedExceptionListener
    941                    // uses Exception rather than Throwable
    942                    PoolUtils.checkRethrow(t);
    943                    swallowException(new Exception(t));
    944                    // Don't evict on error conditions
    945                    evict = false;
    946                }
    947
    948                if (evict) {
    949                    destroy(evictionKey, underTest, true);
    950                    destroyedByEvictorCount.incrementAndGet();
    951                } else {
    952                    if (testWhileIdle) {
    953                        boolean active = false;
    954                        try {
    955                            factory.activateObject(evictionKey, underTest);
    956                            active = true;
    957                        } catch (final Exception e) {
    958                            destroy(evictionKey, underTest, true);
    959                            destroyedByEvictorCount.incrementAndGet();
    960                        }
    961                        if (active) {
    962                            if (!factory.validateObject(evictionKey, underTest)) {
    963                                destroy(evictionKey, underTest, true);
    964                                destroyedByEvictorCount.incrementAndGet();
    965                            } else {
    966                                try {
    967                                    factory.passivateObject(evictionKey, underTest);
    968                                } catch (final Exception e) {
    969                                    destroy(evictionKey, underTest, true);
    970                                    destroyedByEvictorCount.incrementAndGet();
    971                                }
    972                            }
    973                        }
    974                    }
    975                    if (!underTest.endEvictionTest(idleObjects)) {
    976                        // TODO - May need to add code here once additional
    977                        // states are used
    978                    }
    979                }
    980            }
    981        }
    982    }
    983
    984    /**
    985     * Create a new pooled object.
    986     *
    987     * @param key Key associated with new pooled object
    988     *
    989     * @return The new, wrapped pooled object
    990     *
    991     * @throws Exception If the objection creation fails
    992     */
    993    private PooledObject<T> create(final K key) throws Exception {
    994        int maxTotalPerKeySave = getMaxTotalPerKey(); // Per key
    995        if (maxTotalPerKeySave < 0) {
    996            maxTotalPerKeySave = Integer.MAX_VALUE;
    997        }
    998        final int maxTotal = getMaxTotal();   // All keys
    999
    1000        final ObjectDeque<T> objectDeque = poolMap.get(key);
    1001
    1002        // Check against the overall limit
    1003        boolean loop = true;
    1004
    1005        while (loop) {
    1006            final int newNumTotal = numTotal.incrementAndGet();
    1007            if (maxTotal > -1 && newNumTotal > maxTotal) {
    1008                numTotal.decrementAndGet();
    1009                if (getNumIdle() == 0) {
    1010                    return null;
    1011                }
    1012                clearOldest();
    1013            } else {
    1014                loop = false;
    1015            }
    1016        }
    1017
    1018        // Flag that indicates if create should:
    1019        // - TRUE:  call the factory to create an object
    1020        // - FALSE: return null
    1021        // - null:  loop and re-test the condition that determines whether to
    1022        //          call the factory
    1023        Boolean create = null;
    1024        while (create == null) {
    1025            synchronized (objectDeque.makeObjectCountLock) {
    1026                final long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
    1027                // Check against the per key limit
    1028                if (newCreateCount > maxTotalPerKeySave) {
    1029                    // The key is currently at capacity or in the process of
    1030                    // making enough new objects to take it to capacity.
    1031                    objectDeque.getCreateCount().decrementAndGet();
    1032                    if (objectDeque.makeObjectCount == 0) {
    1033                        // There are no makeObject() calls in progress for this
    1034                        // key so the key is at capacity. Do not attempt to
    1035                        // create a new object. Return and wait for an object to
    1036                        // be returned.
    1037                        create = Boolean.FALSE;
    1038                    } else {
    1039                        // There are makeObject() calls in progress that might
    1040                        // bring the pool to capacity. Those calls might also
    1041                        // fail so wait until they complete and then re-test if
    1042                        // the pool is at capacity or not.
    1043                        objectDeque.makeObjectCountLock.wait();
    1044                    }
    1045                } else {
    1046                    // The pool is not at capacity. Create a new object.
    1047                    objectDeque.makeObjectCount++;
    1048                    create = Boolean.TRUE;
    1049                }
    1050            }
    1051        }
    1052
    1053        if (!create.booleanValue()) {
    1054            numTotal.decrementAndGet();
    1055            return null;
    1056        }
    1057
    1058        PooledObject<T> p = null;
    1059        try {
    1060            p = factory.makeObject(key);
    1061        } catch (final Exception e) {
    1062            numTotal.decrementAndGet();
    1063            objectDeque.getCreateCount().decrementAndGet();
    1064            throw e;
    1065        } finally {
    1066            synchronized (objectDeque.makeObjectCountLock) {
    1067                objectDeque.makeObjectCount--;
    1068                objectDeque.makeObjectCountLock.notifyAll();
    1069            }
    1070        }
    1071
    1072        createdCount.incrementAndGet();
    1073        objectDeque.getAllObjects().put(new IdentityWrapper<>(p.getObject()), p);
    1074        return p;
    1075    }
    1076
    1077    /**
    1078     * Destroy the wrapped, pooled object.
    1079     *
    1080     * @param key The key associated with the object to destroy.
    1081     * @param toDestroy The wrapped object to be destroyed
    1082     * @param always Should the object be destroyed even if it is not currently
    1083     *               in the set of idle objects for the given key
    1084     * @return {@code true} if the object was destroyed, otherwise {@code false}
    1085     * @throws Exception If the object destruction failed
    1086     */
    1087    private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always)
    1088            throws Exception {
    1089
    1090        final ObjectDeque<T> objectDeque = register(key);
    1091
    1092        try {
    1093            final boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy);
    1094
    1095            if (isIdle || always) {
    1096                objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject()));
    1097                toDestroy.invalidate();
    1098
    1099                try {
    1100                    factory.destroyObject(key, toDestroy);
    1101                } finally {
    1102                    objectDeque.getCreateCount().decrementAndGet();
    1103                    destroyedCount.incrementAndGet();
    1104                    numTotal.decrementAndGet();
    1105                }
    1106                return true;
    1107            }
    1108            return false;
    1109        } finally {
    1110            deregister(key);
    1111        }
    1112    }
    1113
    1114
    1115    /**
    1116     * Register the use of a key by an object.
    1117     * <p>
    1118     * register() and deregister() must always be used as a pair.
    1119     *
    1120     * @param k The key to register
    1121     *
    1122     * @return The objects currently associated with the given key. If this
    1123     *         method returns without throwing an exception then it will never
    1124     *         return null.
    1125     */
    1126    private ObjectDeque<T> register(final K k) {
    1127        Lock lock = keyLock.readLock();
    1128        ObjectDeque<T> objectDeque = null;
    1129        try {
    1130            lock.lock();
    1131            objectDeque = poolMap.get(k);
    1132            if (objectDeque == null) {
    1133                // Upgrade to write lock
    1134                lock.unlock();
    1135                lock = keyLock.writeLock();
    1136                lock.lock();
    1137                objectDeque = poolMap.get(k);
    1138                if (objectDeque == null) {
    1139                    objectDeque = new ObjectDeque<>(fairness);
    1140                    objectDeque.getNumInterested().incrementAndGet();
    1141                    // NOTE: Keys must always be added to both poolMap and
    1142                    //       poolKeyList at the same time while protected by
    1143                    //       keyLock.writeLock()
    1144                    poolMap.put(k, objectDeque);
    1145                    poolKeyList.add(k);
    1146                } else {
    1147                    objectDeque.getNumInterested().incrementAndGet();
    1148                }
    1149            } else {
    1150                objectDeque.getNumInterested().incrementAndGet();
    1151            }
    1152        } finally {
    1153            lock.unlock();
    1154        }
    1155        return objectDeque;
    1156    }
    1157
    1158    /**
    1159     * De-register the use of a key by an object.
    1160     * <p>
    1161     * register() and deregister() must always be used as a pair.
    1162     *
    1163     * @param k The key to de-register
    1164     */
    1165    private void deregister(final K k) {
    1166        ObjectDeque<T> objectDeque;
    1167
    1168        objectDeque = poolMap.get(k);
    1169        final long numInterested = objectDeque.getNumInterested().decrementAndGet();
    1170        if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
    1171            // Potential to remove key
    1172            final Lock writeLock = keyLock.writeLock();
    1173            writeLock.lock();
    1174            try {
    1175                if (objectDeque.getCreateCount().get() == 0 &&
    1176                        objectDeque.getNumInterested().get() == 0) {
    1177                    // NOTE: Keys must always be removed from both poolMap and
    1178                    //       poolKeyList at the same time while protected by
    1179                    //       keyLock.writeLock()
    1180                    poolMap.remove(k);
    1181                    poolKeyList.remove(k);
    1182                }
    1183            } finally {
    1184                writeLock.unlock();
    1185            }
    1186        }
    1187    }
    1188
    1189    @Override
    1190    void ensureMinIdle() throws Exception {
    1191        final int minIdlePerKeySave = getMinIdlePerKey();
    1192        if (minIdlePerKeySave < 1) {
    1193            return;
    1194        }
    1195
    1196        for (final K k : poolMap.keySet()) {
    1197            ensureMinIdle(k);
    1198        }
    1199    }
    1200
    1201    /**
    1202     * Ensure that the configured number of minimum idle objects is available in
    1203     * the pool for the given key.
    1204     *
    1205     * @param key The key to check for idle objects
    1206     *
    1207     * @throws Exception If a new object is required and cannot be created
    1208     */
    1209    private void ensureMinIdle(final K key) throws Exception {
    1210        // Calculate current pool objects
    1211        ObjectDeque<T> objectDeque = poolMap.get(key);
    1212
    1213        // objectDeque == null is OK here. It is handled correctly by both
    1214        // methods called below.
    1215
    1216        // this method isn't synchronized so the
    1217        // calculateDeficit is done at the beginning
    1218        // as a loop limit and a second time inside the loop
    1219        // to stop when another thread already returned the
    1220        // needed objects
    1221        final int deficit = calculateDeficit(objectDeque);
    1222
    1223        for (int i = 0; i < deficit && calculateDeficit(objectDeque) > 0; i++) {
    1224            addObject(key);
    1225            // If objectDeque was null, it won't be any more. Obtain a reference
    1226            // to it so the deficit can be correctly calculated. It needs to
    1227            // take account of objects created in other threads.
    1228            if (objectDeque == null) {
    1229                objectDeque = poolMap.get(key);
    1230            }
    1231        }
    1232    }
    1233
    1234    /**
    1235     * Create an object using the {@link KeyedPooledObjectFactory#makeObject
    1236     * factory}, passivate it, and then place it in the idle object pool.
    1237     * <code>addObject</code> is useful for "pre-loading" a pool with idle
    1238     * objects.
    1239     *
    1240     * @param key the key a new instance should be added to
    1241     *
    1242     * @throws Exception when {@link KeyedPooledObjectFactory#makeObject}
    1243     *                   fails.
    1244     */
    1245    @Override
    1246    public void addObject(final K key) throws Exception {
    1247        assertOpen();
    1248        register(key);
    1249        try {
    1250            final PooledObject<T> p = create(key);
    1251            addIdleObject(key, p);
    1252        } finally {
    1253            deregister(key);
    1254        }
    1255    }
    1256
    1257    /**
    1258     * Add an object to the set of idle objects for a given key.
    1259     *
    1260     * @param key The key to associate with the idle object
    1261     * @param p The wrapped object to add.
    1262     *
    1263     * @throws Exception If the associated factory fails to passivate the object
    1264     */
    1265    private void addIdleObject(final K key, final PooledObject<T> p) throws Exception {
    1266
    1267        if (p != null) {
    1268            factory.passivateObject(key, p);
    1269            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
    1270                    poolMap.get(key).getIdleObjects();
    1271            if (getLifo()) {
    1272                idleObjects.addFirst(p);
    1273            } else {
    1274                idleObjects.addLast(p);
    1275            }
    1276        }
    1277    }
    1278
    1279    /**
    1280     * Registers a key for pool control and ensures that
    1281     * {@link #getMinIdlePerKey()} idle instances are created.
    1282     *
    1283     * @param key - The key to register for pool control.
    1284     *
    1285     * @throws Exception If the associated factory throws an exception
    1286     */
    1287    public void preparePool(final K key) throws Exception {
    1288        final int minIdlePerKeySave = getMinIdlePerKey();
    1289        if (minIdlePerKeySave < 1) {
    1290            return;
    1291        }
    1292        ensureMinIdle(key);
    1293    }
    1294
    1295    /**
    1296     * Calculate the number of objects to test in a run of the idle object
    1297     * evictor.
    1298     *
    1299     * @return The number of objects to test for validity
    1300     */
    1301    private int getNumTests() {
    1302        final int totalIdle = getNumIdle();
    1303        final int numTests = getNumTestsPerEvictionRun();
    1304        if (numTests >= 0) {
    1305            return Math.min(numTests, totalIdle);
    1306        }
    1307        return(int)(Math.ceil(totalIdle/Math.abs((double)numTests)));
    1308    }
    1309
    1310    /**
    1311     * Calculate the number of objects that need to be created to attempt to
    1312     * maintain the minimum number of idle objects while not exceeded the limits
    1313     * on the maximum number of objects either per key or totally.
    1314     *
    1315     * @param objectDeque   The set of objects to check
    1316     *
    1317     * @return The number of new objects to create
    1318     */
    1319    private int calculateDeficit(final ObjectDeque<T> objectDeque) {
    1320
    1321        if (objectDeque == null) {
    1322            return getMinIdlePerKey();
    1323        }
    1324
    1325        // Used more than once so keep a local copy so the value is consistent
    1326        final int maxTotal = getMaxTotal();
    1327        final int maxTotalPerKeySave = getMaxTotalPerKey();
    1328
    1329        int objectDefecit = 0;
    1330
    1331        // Calculate no of objects needed to be created, in order to have
    1332        // the number of pooled objects < maxTotalPerKey();
    1333        objectDefecit = getMinIdlePerKey() - objectDeque.getIdleObjects().size();
    1334        if (maxTotalPerKeySave > 0) {
    1335            final int growLimit = Math.max(0,
    1336                    maxTotalPerKeySave - objectDeque.getIdleObjects().size());
    1337            objectDefecit = Math.min(objectDefecit, growLimit);
    1338        }
    1339
    1340        // Take the maxTotal limit into account
    1341        if (maxTotal > 0) {
    1342            final int growLimit = Math.max(0, maxTotal - getNumActive() - getNumIdle());
    1343            objectDefecit = Math.min(objectDefecit, growLimit);
    1344        }
    1345
    1346        return objectDefecit;
    1347    }
    1348
    1349
    1350    //--- JMX support ----------------------------------------------------------
    1351
    1352    @Override
    1353    public Map<String,Integer> getNumActivePerKey() {
    1354        final HashMap<String,Integer> result = new HashMap<>();
    1355
    1356        final Iterator<Entry<K,ObjectDeque<T>>> iter = poolMap.entrySet().iterator();
    1357        while (iter.hasNext()) {
    1358            final Entry<K,ObjectDeque<T>> entry = iter.next();
    1359            if (entry != null) {
    1360                final K key = entry.getKey();
    1361                final ObjectDeque<T> objectDequeue = entry.getValue();
    1362                if (key != null && objectDequeue != null) {
    1363                    result.put(key.toString(), Integer.valueOf(
    1364                            objectDequeue.getAllObjects().size() -
    1365                            objectDequeue.getIdleObjects().size()));
    1366                }
    1367            }
    1368        }
    1369        return result;
    1370    }
    1371
    1372    /**
    1373     * Return an estimate of the number of threads currently blocked waiting for
    1374     * an object from the pool. This is intended for monitoring only, not for
    1375     * synchronization control.
    1376     *
    1377     * @return The estimate of the number of threads currently blocked waiting
    1378     *         for an object from the pool
    1379     */
    1380    @Override
    1381    public int getNumWaiters() {
    1382        int result = 0;
    1383
    1384        if (getBlockWhenExhausted()) {
    1385            final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
    1386
    1387            while (iter.hasNext()) {
    1388                // Assume no overflow
    1389                result += iter.next().getIdleObjects().getTakeQueueLength();
    1390            }
    1391        }
    1392
    1393        return result;
    1394    }
    1395
    1396    /**
    1397     * Return an estimate of the number of threads currently blocked waiting for
    1398     * an object from the pool for each key. This is intended for
    1399     * monitoring only, not for synchronization control.
    1400     *
    1401     * @return The estimate of the number of threads currently blocked waiting
    1402     *         for an object from the pool for each key
    1403     */
    1404    @Override
    1405    public Map<String,Integer> getNumWaitersByKey() {
    1406        final Map<String,Integer> result = new HashMap<>();
    1407
    1408        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
    1409            final K k = entry.getKey();
    1410            final ObjectDeque<T> deque = entry.getValue();
    1411            if (deque != null) {
    1412                if (getBlockWhenExhausted()) {
    1413                    result.put(k.toString(), Integer.valueOf(
    1414                            deque.getIdleObjects().getTakeQueueLength()));
    1415                } else {
    1416                    result.put(k.toString(), Integer.valueOf(0));
    1417                }
    1418            }
    1419        }
    1420        return result;
    1421    }
    1422
    1423    /**
    1424     * Provides information on all the objects in the pool, both idle (waiting
    1425     * to be borrowed) and active (currently borrowed).
    1426     * <p>
    1427     * Note: This is named listAllObjects so it is presented as an operation via
    1428     * JMX. That means it won't be invoked unless the explicitly requested
    1429     * whereas all attributes will be automatically requested when viewing the
    1430     * attributes for an object in a tool like JConsole.
    1431     *
    1432     * @return Information grouped by key on all the objects in the pool
    1433     */
    1434    @Override
    1435    public Map<String,List<DefaultPooledObjectInfo>> listAllObjects() {
    1436        final Map<String,List<DefaultPooledObjectInfo>> result =
    1437                new HashMap<>();
    1438
    1439        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
    1440            final K k = entry.getKey();
    1441            final ObjectDeque<T> deque = entry.getValue();
    1442            if (deque != null) {
    1443                final List<DefaultPooledObjectInfo> list =
    1444                        new ArrayList<>();
    1445                result.put(k.toString(), list);
    1446                for (final PooledObject<T> p : deque.getAllObjects().values()) {
    1447                    list.add(new DefaultPooledObjectInfo(p));
    1448                }
    1449            }
    1450        }
    1451        return result;
    1452    }
    1453
    1454
    1455    //--- inner classes ----------------------------------------------
    1456
    1457    /**
    1458     * Maintains information on the per key queue for a given key.
    1459     *
    1460     * @param <S> type of objects in the pool
    1461     */
    1462    private class ObjectDeque<S> {
    1463
    1464        private final LinkedBlockingDeque<PooledObject<S>> idleObjects;
    1465
    1466        /*
    1467         * Number of instances created - number destroyed.
    1468         * Invariant: createCount <= maxTotalPerKey
    1469         */
    1470        private final AtomicInteger createCount = new AtomicInteger(0);
    1471
    1472        private long makeObjectCount = 0;
    1473        private final Object makeObjectCountLock = new Object();
    1474
    1475        /*
    1476         * The map is keyed on pooled instances, wrapped to ensure that
    1477         * they work properly as keys.
    1478         */
    1479        private final Map<IdentityWrapper<S>, PooledObject<S>> allObjects =
    1480                new ConcurrentHashMap<>();
    1481
    1482        /*
    1483         * Number of threads with registered interest in this key.
    1484         * register(K) increments this counter and deRegister(K) decrements it.
    1485         * Invariant: empty keyed pool will not be dropped unless numInterested
    1486         *            is 0.
    1487         */
    1488        private final AtomicLong numInterested = new AtomicLong(0);
    1489
    1490        /**
    1491         * Create a new ObjecDeque with the given fairness policy.
    1492         * @param fairness true means client threads waiting to borrow / return instances
    1493         * will be served as if waiting in a FIFO queue.
    1494         */
    1495        public ObjectDeque(final boolean fairness) {
    1496            idleObjects = new LinkedBlockingDeque<>(fairness);
    1497        }
    1498
    1499        /**
    1500         * Obtain the idle objects for the current key.
    1501         *
    1502         * @return The idle objects
    1503         */
    1504        public LinkedBlockingDeque<PooledObject<S>> getIdleObjects() {
    1505            return idleObjects;
    1506        }
    1507
    1508        /**
    1509         * Obtain the count of the number of objects created for the current
    1510         * key.
    1511         *
    1512         * @return The number of objects created for this key
    1513         */
    1514        public AtomicInteger getCreateCount() {
    1515            return createCount;
    1516        }
    1517
    1518        /**
    1519         * Obtain the number of threads with an interest registered in this key.
    1520         *
    1521         * @return The number of threads with a registered interest in this key
    1522         */
    1523        public AtomicLong getNumInterested() {
    1524            return numInterested;
    1525        }
    1526
    1527        /**
    1528         * Obtain all the objects for the current key.
    1529         *
    1530         * @return All the objects
    1531         */
    1532        public Map<IdentityWrapper<S>, PooledObject<S>> getAllObjects() {
    1533            return allObjects;
    1534        }
    1535
    1536        @Override
    1537        public String toString() {
    1538            final StringBuilder builder = new StringBuilder();
    1539            builder.append("ObjectDeque [idleObjects=");
    1540            builder.append(idleObjects);
    1541            builder.append(", createCount=");
    1542            builder.append(createCount);
    1543            builder.append(", allObjects=");
    1544            builder.append(allObjects);
    1545            builder.append(", numInterested=");
    1546            builder.append(numInterested);
    1547            builder.append("]");
    1548            return builder.toString();
    1549        }
    1550
    1551    }
    1552
    1553    //--- configuration attributes ---------------------------------------------
    1554    private volatile int maxIdlePerKey =
    1555            GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY;
    1556    private volatile int minIdlePerKey =
    1557            GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY;
    1558    private volatile int maxTotalPerKey =
    1559            GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;
    1560    private final KeyedPooledObjectFactory<K,T> factory;
    1561    private final boolean fairness;
    1562
    1563
    1564    //--- internal attributes --------------------------------------------------
    1565
    1566    /*
    1567     * My hash of sub-pools (ObjectQueue). The list of keys <b>must</b> be kept
    1568     * in step with {@link #poolKeyList} using {@link #keyLock} to ensure any
    1569     * changes to the list of current keys is made in a thread-safe manner.
    1570     */
    1571    private final Map<K,ObjectDeque<T>> poolMap =
    1572            new ConcurrentHashMap<>(); // @GuardedBy("keyLock") for write access (and some read access)
    1573    /*
    1574     * List of pool keys - used to control eviction order. The list of keys
    1575     * <b>must</b> be kept in step with {@link #poolMap} using {@link #keyLock}
    1576     * to ensure any changes to the list of current keys is made in a
    1577     * thread-safe manner.
    1578     */
    1579    private final List<K> poolKeyList = new ArrayList<>(); // @GuardedBy("keyLock")
    1580    private final ReadWriteLock keyLock = new ReentrantReadWriteLock(true);
    1581    /*
    1582     * The combined count of the currently active objects for all keys and those
    1583     * in the process of being created. Under load, it may exceed
    1584     * {@link #maxTotal} but there will never be more than {@link #maxTotal}
    1585     * created at any one time.
    1586     */
    1587    private final AtomicInteger numTotal = new AtomicInteger(0);
    1588    private Iterator<K> evictionKeyIterator = null; // @GuardedBy("evictionLock")
    1589    private K evictionKey = null; // @GuardedBy("evictionLock")
    1590
    1591    // JMX specific attributes
    1592    private static final String ONAME_BASE =
    1593            "org.apache.commons.pool2:type=GenericKeyedObjectPool,name=";
    1594
    1595    @Override
    1596    protected void toStringAppendFields(final StringBuilder builder) {
    1597        super.toStringAppendFields(builder);
    1598        builder.append(", maxIdlePerKey=");
    1599        builder.append(maxIdlePerKey);
    1600        builder.append(", minIdlePerKey=");
    1601        builder.append(minIdlePerKey);
    1602        builder.append(", maxTotalPerKey=");
    1603        builder.append(maxTotalPerKey);
    1604        builder.append(", factory=");
    1605        builder.append(factory);
    1606        builder.append(", fairness=");
    1607        builder.append(fairness);
    1608        builder.append(", poolMap=");
    1609        builder.append(poolMap);
    1610        builder.append(", poolKeyList=");
    1611        builder.append(poolKeyList);
    1612        builder.append(", keyLock=");
    1613        builder.append(keyLock);
    1614        builder.append(", numTotal=");
    1615        builder.append(numTotal);
    1616        builder.append(", evictionKeyIterator=");
    1617        builder.append(evictionKeyIterator);
    1618        builder.append(", evictionKey=");
    1619        builder.append(evictionKey);
    1620    }
    1621}