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