GenericKeyedObjectPool.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.pool2.impl;

  18. import java.time.Duration;
  19. import java.time.Instant;
  20. import java.util.ArrayList;
  21. import java.util.Deque;
  22. import java.util.HashMap;
  23. import java.util.Iterator;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Map.Entry;
  27. import java.util.NoSuchElementException;
  28. import java.util.Objects;
  29. import java.util.TreeMap;
  30. import java.util.concurrent.ConcurrentHashMap;
  31. import java.util.concurrent.TimeUnit;
  32. import java.util.concurrent.atomic.AtomicBoolean;
  33. import java.util.concurrent.atomic.AtomicInteger;
  34. import java.util.concurrent.atomic.AtomicLong;
  35. import java.util.concurrent.locks.Lock;
  36. import java.util.concurrent.locks.ReadWriteLock;
  37. import java.util.concurrent.locks.ReentrantReadWriteLock;
  38. import java.util.stream.Collectors;

  39. import org.apache.commons.pool2.DestroyMode;
  40. import org.apache.commons.pool2.KeyedObjectPool;
  41. import org.apache.commons.pool2.KeyedPooledObjectFactory;
  42. import org.apache.commons.pool2.PoolUtils;
  43. import org.apache.commons.pool2.PooledObject;
  44. import org.apache.commons.pool2.PooledObjectState;
  45. import org.apache.commons.pool2.SwallowedExceptionListener;
  46. import org.apache.commons.pool2.UsageTracking;

  47. /**
  48.  * A configurable {@code KeyedObjectPool} implementation.
  49.  * <p>
  50.  * When coupled with the appropriate {@link KeyedPooledObjectFactory},
  51.  * {@code GenericKeyedObjectPool} provides robust pooling functionality for
  52.  * keyed objects. A {@code GenericKeyedObjectPool} can be viewed as a map
  53.  * of sub-pools, keyed on the (unique) key values provided to the
  54.  * {@link #preparePool preparePool}, {@link #addObject addObject} or
  55.  * {@link #borrowObject borrowObject} methods. Each time a new key value is
  56.  * provided to one of these methods, a sub-new pool is created under the given
  57.  * key to be managed by the containing {@code GenericKeyedObjectPool.}
  58.  * </p>
  59.  * <p>
  60.  * Note that the current implementation uses a ConcurrentHashMap which uses
  61.  * equals() to compare keys.
  62.  * This means that distinct instance keys must be distinguishable using equals.
  63.  * </p>
  64.  * <p>
  65.  * Optionally, one may configure the pool to examine and possibly evict objects
  66.  * as they sit idle in the pool and to ensure that a minimum number of idle
  67.  * objects is maintained for each key. This is performed by an "idle object
  68.  * eviction" thread, which runs asynchronously. Caution should be used when
  69.  * configuring this optional feature. Eviction runs contend with client threads
  70.  * for access to objects in the pool, so if they run too frequently performance
  71.  * issues may result.
  72.  * </p>
  73.  * <p>
  74.  * Implementation note: To prevent possible deadlocks, care has been taken to
  75.  * ensure that no call to a factory method will occur within a synchronization
  76.  * block. See POOL-125 and DBCP-44 for more information.
  77.  * </p>
  78.  * <p>
  79.  * This class is intended to be thread-safe.
  80.  * </p>
  81.  *
  82.  * @see GenericObjectPool
  83.  * @param <K> The type of keys maintained by this pool.
  84.  * @param <T> Type of element pooled in this pool.
  85.  * @since 2.0
  86.  */
  87. public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T>
  88.         implements KeyedObjectPool<K, T>, GenericKeyedObjectPoolMXBean<K>, UsageTracking<T> {

  89.     /**
  90.      * Maintains information on the per key queue for a given key.
  91.      *
  92.      * @param <S> type of objects in the pool
  93.      */
  94.     private static final class ObjectDeque<S> {

  95.         private final LinkedBlockingDeque<PooledObject<S>> idleObjects;

  96.         /*
  97.          * Number of instances created - number destroyed.
  98.          * Invariant: createCount <= maxTotalPerKey
  99.          */
  100.         private final AtomicInteger createCount = new AtomicInteger();

  101.         private long makeObjectCount;
  102.         private final Object makeObjectCountLock = new Object();

  103.         /*
  104.          * The map is keyed on pooled instances, wrapped to ensure that
  105.          * they work properly as keys.
  106.          */
  107.         private final Map<IdentityWrapper<S>, PooledObject<S>> allObjects =
  108.                 new ConcurrentHashMap<>();

  109.         /*
  110.          * Number of threads with registered interest in this key.
  111.          * register(K) increments this counter and deRegister(K) decrements it.
  112.          * Invariant: empty keyed pool will not be dropped unless numInterested
  113.          *            is 0.
  114.          */
  115.         private final AtomicLong numInterested = new AtomicLong();

  116.         /**
  117.          * Constructs a new ObjectDeque with the given fairness policy.
  118.          * @param fairness true means client threads waiting to borrow / return instances
  119.          * will be served as if waiting in a FIFO queue.
  120.          */
  121.         public ObjectDeque(final boolean fairness) {
  122.             idleObjects = new LinkedBlockingDeque<>(fairness);
  123.         }

  124.         /**
  125.          * Gets all the objects for the current key.
  126.          *
  127.          * @return All the objects
  128.          */
  129.         public Map<IdentityWrapper<S>, PooledObject<S>> getAllObjects() {
  130.             return allObjects;
  131.         }

  132.         /**
  133.          * Gets the number of instances created - number destroyed.
  134.          * Should always be less than or equal to maxTotalPerKey.
  135.          *
  136.          * @return The net instance addition count for this deque
  137.          */
  138.         public AtomicInteger getCreateCount() {
  139.             return createCount;
  140.         }

  141.         /**
  142.          * Gets the idle objects for the current key.
  143.          *
  144.          * @return The idle objects
  145.          */
  146.         public LinkedBlockingDeque<PooledObject<S>> getIdleObjects() {
  147.             return idleObjects;
  148.         }

  149.         /**
  150.          * Gets the number of threads with an interest registered in this key.
  151.          *
  152.          * @return The number of threads with a registered interest in this key
  153.          */
  154.         public AtomicLong getNumInterested() {
  155.             return numInterested;
  156.         }

  157.         @Override
  158.         public String toString() {
  159.             final StringBuilder builder = new StringBuilder();
  160.             builder.append("ObjectDeque [idleObjects=");
  161.             builder.append(idleObjects);
  162.             builder.append(", createCount=");
  163.             builder.append(createCount);
  164.             builder.append(", allObjects=");
  165.             builder.append(allObjects);
  166.             builder.append(", numInterested=");
  167.             builder.append(numInterested);
  168.             builder.append("]");
  169.             return builder.toString();
  170.         }

  171.     }

  172.     private static final Integer ZERO = Integer.valueOf(0);

  173.     // JMX specific attributes
  174.     private static final String ONAME_BASE =
  175.             "org.apache.commons.pool2:type=GenericKeyedObjectPool,name=";

  176.     private volatile int maxIdlePerKey =
  177.             GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY;

  178.     private volatile int minIdlePerKey =
  179.             GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY;

  180.     private volatile int maxTotalPerKey =
  181.             GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;

  182.     private final KeyedPooledObjectFactory<K, T> factory;

  183.     private final boolean fairness;

  184.     /*
  185.      * My hash of sub-pools (ObjectQueue). The list of keys <strong>must</strong> be kept
  186.      * in step with {@link #poolKeyList} using {@link #keyLock} to ensure any
  187.      * changes to the list of current keys is made in a thread-safe manner.
  188.      */
  189.     private final Map<K, ObjectDeque<T>> poolMap =
  190.             new ConcurrentHashMap<>(); // @GuardedBy("keyLock") for write access (and some read access)

  191.     /*
  192.      * List of pool keys - used to control eviction order. The list of keys
  193.      * <strong>must</strong> be kept in step with {@link #poolMap} using {@link #keyLock}
  194.      * to ensure any changes to the list of current keys is made in a
  195.      * thread-safe manner.
  196.      */
  197.     private final ArrayList<K> poolKeyList = new ArrayList<>(); // @GuardedBy("keyLock")

  198.     private final ReadWriteLock keyLock = new ReentrantReadWriteLock(true);

  199.     /*
  200.      * The combined count of the currently active objects for all keys and those
  201.      * in the process of being created. Under load, it may exceed
  202.      * {@link #maxTotal} but there will never be more than {@link #maxTotal}
  203.      * created at any one time.
  204.      */
  205.     private final AtomicInteger numTotal = new AtomicInteger();

  206.     private Iterator<K> evictionKeyIterator; // @GuardedBy("evictionLock")

  207.     private K evictionKey; // @GuardedBy("evictionLock")

  208.     /**
  209.      * Constructs a new {@code GenericKeyedObjectPool} using defaults from
  210.      * {@link GenericKeyedObjectPoolConfig}.
  211.      * @param factory the factory to be used to create entries
  212.      */
  213.     public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K, T> factory) {
  214.         this(factory, new GenericKeyedObjectPoolConfig<>());
  215.     }

  216.     /**
  217.      * Constructs a new {@code GenericKeyedObjectPool} using a specific
  218.      * configuration.
  219.      *
  220.      * @param factory the factory to be used to create entries
  221.      * @param config    The configuration to use for this pool instance. The
  222.      *                  configuration is used by value. Subsequent changes to
  223.      *                  the configuration object will not be reflected in the
  224.      *                  pool.
  225.      */
  226.     public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K, T> factory,
  227.             final GenericKeyedObjectPoolConfig<T> config) {

  228.         super(config, ONAME_BASE, config.getJmxNamePrefix());

  229.         if (factory == null) {
  230.             jmxUnregister(); // tidy up
  231.             throw new IllegalArgumentException("Factory may not be null");
  232.         }
  233.         this.factory = factory;
  234.         this.fairness = config.getFairness();

  235.         setConfig(config);
  236.     }

  237.     /**
  238.      * Creates a new {@code GenericKeyedObjectPool} that tracks and destroys
  239.      * objects that are checked out, but never returned to the pool.
  240.      *
  241.      * @param factory   The object factory to be used to create object instances
  242.      *                  used by this pool
  243.      * @param config    The base pool configuration to use for this pool instance.
  244.      *                  The configuration is used by value. Subsequent changes to
  245.      *                  the configuration object will not be reflected in the
  246.      *                  pool.
  247.      * @param abandonedConfig  Configuration for abandoned object identification
  248.      *                         and removal.  The configuration is used by value.
  249.      * @since 2.10.0
  250.      */
  251.     public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K, T> factory,
  252.             final GenericKeyedObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
  253.         this(factory, config);
  254.         setAbandonedConfig(abandonedConfig);
  255.     }

  256.     /**
  257.      * Add an object to the set of idle objects for a given key.
  258.      * If the object is null this is a no-op.
  259.      *
  260.      * @param key The key to associate with the idle object
  261.      * @param p The wrapped object to add.
  262.      * @throws Exception If the associated factory fails to passivate the object
  263.      */
  264.     private void addIdleObject(final K key, final PooledObject<T> p) throws Exception {
  265.         if (!PooledObject.isNull(p)) {
  266.             factory.passivateObject(key, p);
  267.             final LinkedBlockingDeque<PooledObject<T>> idleObjects = poolMap.get(key).getIdleObjects();
  268.             if (getLifo()) {
  269.                 idleObjects.addFirst(p);
  270.             } else {
  271.                 idleObjects.addLast(p);
  272.             }
  273.         }
  274.     }

  275.     /**
  276.      * Create an object using the {@link KeyedPooledObjectFactory#makeObject
  277.      * factory}, passivate it, and then place it in the idle object pool.
  278.      * {@code addObject} is useful for "pre-loading" a pool with idle
  279.      * objects.
  280.      * <p>
  281.      * If there is no capacity available to add to the pool under the given key,
  282.      * this is a no-op (no exception, no impact to the pool).
  283.      * </p>
  284.      * <p>
  285.      * If the factory returns null when creating an instance,
  286.      * a {@code NullPointerException} is thrown.
  287.      * </p>
  288.      *
  289.      * @param key the key a new instance should be added to
  290.      * @throws Exception when {@link KeyedPooledObjectFactory#makeObject}
  291.      *                   fails.
  292.      */
  293.     @Override
  294.     public void addObject(final K key) throws Exception {
  295.         assertOpen();
  296.         register(key);
  297.         try {
  298.             addIdleObject(key, create(key));
  299.         } finally {
  300.             deregister(key);
  301.         }
  302.     }

  303.     /**
  304.      * Equivalent to <code>{@link #borrowObject(Object, long) borrowObject}(key,
  305.      * {@link #getMaxWaitDuration()})</code>.
  306.      *
  307.      * {@inheritDoc}
  308.      */
  309.     @Override
  310.     public T borrowObject(final K key) throws Exception {
  311.         return borrowObject(key, getMaxWaitDuration().toMillis());
  312.     }

  313.     /**
  314.      * Borrows an object from the sub-pool associated with the given key using
  315.      * the specified waiting time which only applies if
  316.      * {@link #getBlockWhenExhausted()} is true.
  317.      * <p>
  318.      * If there is one or more idle instances available in the sub-pool
  319.      * associated with the given key, then an idle instance will be selected
  320.      * based on the value of {@link #getLifo()}, activated and returned.  If
  321.      * activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set to
  322.      * {@code true} and validation fails, the instance is destroyed and the
  323.      * next available instance is examined.  This continues until either a valid
  324.      * instance is returned or there are no more idle instances available.
  325.      * </p>
  326.      * <p>
  327.      * If there are no idle instances available in the sub-pool associated with
  328.      * the given key, behavior depends on the {@link #getMaxTotalPerKey()
  329.      * maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable)
  330.      * {@link #getBlockWhenExhausted()} and the value passed in to the
  331.      * {@code borrowMaxWaitMillis} parameter. If the number of instances checked
  332.      * out from the sub-pool under the given key is less than
  333.      * {@code maxTotalPerKey} and the total number of instances in
  334.      * circulation (under all keys) is less than {@code maxTotal}, a new
  335.      * instance is created, activated and (if applicable) validated and returned
  336.      * to the caller. If validation fails, a {@code NoSuchElementException}
  337.      * will be thrown. If the factory returns null when creating an instance,
  338.      * a {@code NullPointerException} is thrown.
  339.      * </p>
  340.      * <p>
  341.      * If the associated sub-pool is exhausted (no available idle instances and
  342.      * no capacity to create new ones), this method will either block
  343.      * ({@link #getBlockWhenExhausted()} is true) or throw a
  344.      * {@code NoSuchElementException}
  345.      * ({@link #getBlockWhenExhausted()} is false).
  346.      * The length of time that this method will block when
  347.      * {@link #getBlockWhenExhausted()} is true is determined by the value
  348.      * passed in to the {@code borrowMaxWait} parameter.
  349.      * </p>
  350.      * <p>
  351.      * When {@code maxTotal} is set to a positive value and this method is
  352.      * invoked when at the limit with no idle instances available under the requested
  353.      * key, an attempt is made to create room by clearing the oldest 15% of the
  354.      * elements from the keyed sub-pools.
  355.      * </p>
  356.      * <p>
  357.      * When the pool is exhausted, multiple calling threads may be
  358.      * simultaneously blocked waiting for instances to become available. A
  359.      * "fairness" algorithm has been implemented to ensure that threads receive
  360.      * available instances in request arrival order.
  361.      * </p>
  362.      *
  363.      * @param key pool key
  364.      * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
  365.      *                            to become available
  366.      *
  367.      * @return object instance from the keyed pool
  368.      * @throws NoSuchElementException if a keyed object instance cannot be
  369.      *                                returned because the pool is exhausted.
  370.      *
  371.      * @throws Exception if a keyed object instance cannot be returned due to an
  372.      *                   error
  373.      */
  374.     public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception {
  375.         assertOpen();

  376.         final AbandonedConfig ac = this.abandonedConfig;
  377.         if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 &&
  378.                 getNumActive() > getMaxTotal() - 3) {
  379.             removeAbandoned(ac);
  380.         }

  381.         PooledObject<T> p = null;

  382.         // Get local copy of current config so it is consistent for entire
  383.         // method execution
  384.         final boolean blockWhenExhausted = getBlockWhenExhausted();

  385.         boolean create;
  386.         final Instant waitTime = Instant.now();
  387.         final ObjectDeque<T> objectDeque = register(key);

  388.         try {
  389.             while (p == null) {
  390.                 create = false;
  391.                 p = objectDeque.getIdleObjects().pollFirst();
  392.                 if (p == null) {
  393.                     p = create(key);
  394.                     if (!PooledObject.isNull(p)) {
  395.                         create = true;
  396.                     }
  397.                 }
  398.                 if (blockWhenExhausted) {
  399.                     if (PooledObject.isNull(p)) {
  400.                         p = borrowMaxWaitMillis < 0 ? objectDeque.getIdleObjects().takeFirst():
  401.                                 objectDeque.getIdleObjects().pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
  402.                     }
  403.                     if (PooledObject.isNull(p)) {
  404.                         throw new NoSuchElementException(appendStats(
  405.                                 "Timeout waiting for idle object, borrowMaxWaitMillis=" + borrowMaxWaitMillis));
  406.                     }
  407.                 } else if (PooledObject.isNull(p)) {
  408.                     throw new NoSuchElementException(appendStats("Pool exhausted"));
  409.                 }
  410.                 if (!p.allocate()) {
  411.                     p = null;
  412.                 }

  413.                 if (!PooledObject.isNull(p)) {
  414.                     try {
  415.                         factory.activateObject(key, p);
  416.                     } catch (final Exception e) {
  417.                         try {
  418.                             destroy(key, p, true, DestroyMode.NORMAL);
  419.                         } catch (final Exception ignored) {
  420.                             // ignored - activation failure is more important
  421.                         }
  422.                         p = null;
  423.                         if (create) {
  424.                             final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object"));
  425.                             nsee.initCause(e);
  426.                             throw nsee;
  427.                         }
  428.                     }
  429.                     if (!PooledObject.isNull(p) && getTestOnBorrow()) {
  430.                         boolean validate = false;
  431.                         Throwable validationThrowable = null;
  432.                         try {
  433.                             validate = factory.validateObject(key, p);
  434.                         } catch (final Throwable t) {
  435.                             PoolUtils.checkRethrow(t);
  436.                             validationThrowable = t;
  437.                         }
  438.                         if (!validate) {
  439.                             try {
  440.                                 destroy(key, p, true, DestroyMode.NORMAL);
  441.                                 destroyedByBorrowValidationCount.incrementAndGet();
  442.                             } catch (final Exception ignored) {
  443.                                 // ignored - validation failure is more important
  444.                             }
  445.                             p = null;
  446.                             if (create) {
  447.                                 final NoSuchElementException nsee = new NoSuchElementException(
  448.                                         appendStats("Unable to validate object"));
  449.                                 nsee.initCause(validationThrowable);
  450.                                 throw nsee;
  451.                             }
  452.                         }
  453.                     }
  454.                 }
  455.             }
  456.         } finally {
  457.             deregister(key);
  458.         }

  459.         updateStatsBorrow(p, Duration.between(waitTime, Instant.now()));

  460.         return p.getObject();
  461.     }

  462.     /**
  463.      * Calculate the number of objects that need to be created to attempt to
  464.      * maintain the minimum number of idle objects while not exceeded the limits
  465.      * on the maximum number of objects either per key or totally.
  466.      *
  467.      * @param objectDeque   The set of objects to check
  468.      * @return The number of new objects to create
  469.      */
  470.     private int calculateDeficit(final ObjectDeque<T> objectDeque) {

  471.         if (objectDeque == null) {
  472.             return getMinIdlePerKey();
  473.         }

  474.         // Used more than once so keep a local copy so the value is consistent
  475.         final int maxTotal = getMaxTotal();
  476.         final int maxTotalPerKeySave = getMaxTotalPerKey();

  477.         // Calculate no of objects needed to be created, in order to have
  478.         // the number of pooled objects < maxTotalPerKey();
  479.         int objectDefecit = getMinIdlePerKey() - objectDeque.getIdleObjects().size();
  480.         if (maxTotalPerKeySave > 0) {
  481.             final int growLimit = Math.max(0,
  482.                     maxTotalPerKeySave - objectDeque.getIdleObjects().size());
  483.             objectDefecit = Math.min(objectDefecit, growLimit);
  484.         }

  485.         // Take the maxTotal limit into account
  486.         if (maxTotal > 0) {
  487.             final int growLimit = Math.max(0, maxTotal - getNumActive() - getNumIdle());
  488.             objectDefecit = Math.min(objectDefecit, growLimit);
  489.         }

  490.         return objectDefecit;
  491.     }

  492.     /**
  493.      * Clears any objects sitting idle in the pool by removing them from the
  494.      * idle instance sub-pools and then invoking the configured
  495.      * PoolableObjectFactory's
  496.      * {@link KeyedPooledObjectFactory#destroyObject(Object, PooledObject)}
  497.      * method on each idle instance.
  498.      * <p>
  499.      * Implementation notes:
  500.      * <ul>
  501.      * <li>This method does not destroy or effect in any way instances that are
  502.      * checked out when it is invoked.</li>
  503.      * <li>Invoking this method does not prevent objects being returned to the
  504.      * idle instance pool, even during its execution. Additional instances may
  505.      * be returned while removed items are being destroyed.</li>
  506.      * <li>Exceptions encountered destroying idle instances are swallowed
  507.      * but notified via a {@link SwallowedExceptionListener}.</li>
  508.      * </ul>
  509.      */
  510.     @Override
  511.     public void clear() {
  512.         poolMap.keySet().forEach(key -> clear(key, false));
  513.     }

  514.     /**
  515.      * Clears the specified sub-pool, removing all pooled instances
  516.      * corresponding to the given {@code key}. Exceptions encountered
  517.      * destroying idle instances are swallowed but notified via a
  518.      * {@link SwallowedExceptionListener}.
  519.      * <p>
  520.      * If there are clients waiting to borrow objects, this method will
  521.      * attempt to reuse the capacity freed by this operation, adding
  522.      * instances to the most loaded keyed pools.  To avoid triggering
  523.      * possible object creation, use {@link #clear(Object, boolean)}.
  524.      *
  525.      * @param key the key to clear
  526.      */
  527.     @Override
  528.     public void clear(final K key) {
  529.         clear(key, true);
  530.     }

  531.     /**
  532.      * Clears the specified sub-pool, removing all pooled instances
  533.      * corresponding to the given {@code key}. Exceptions encountered
  534.      * destroying idle instances are swallowed but notified via a
  535.      * {@link SwallowedExceptionListener}.
  536.      * <p>
  537.      * If reuseCapacity is true and there are clients waiting to
  538.      * borrow objects, this method will attempt to reuse the capacity freed
  539.      * by this operation, adding instances to the most loaded keyed pools.
  540.      * </p>
  541.      *
  542.      * @param key the key to clear
  543.      * @param reuseCapacity whether or not to reuse freed capacity
  544.      * @since 2.12.0
  545.      */
  546.     public void clear(final K key, final boolean reuseCapacity) {
  547.         // Return immediately if there is no pool under this key.
  548.         if (!poolMap.containsKey(key)) {
  549.             return;
  550.         }
  551.         final ObjectDeque<T> objectDeque = register(key);
  552.         int freedCapacity = 0;
  553.         try {
  554.             final LinkedBlockingDeque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
  555.             PooledObject<T> p = idleObjects.poll();
  556.             while (p != null) {
  557.                 try {
  558.                     if (destroy(key, p, true, DestroyMode.NORMAL)) {
  559.                         freedCapacity++;
  560.                     }
  561.                 } catch (final Exception e) {
  562.                     swallowException(e);
  563.                 }
  564.                 p = idleObjects.poll();
  565.             }
  566.         } finally {
  567.             deregister(key);
  568.         }
  569.         if (reuseCapacity) {
  570.             reuseCapacity(freedCapacity);
  571.         }
  572.     }

  573.     /**
  574.      * Clears oldest 15% of objects in pool.  The method sorts the objects into
  575.      * a TreeMap and then iterates the first 15% for removal.
  576.      */
  577.     public void clearOldest() {

  578.         // build sorted map of idle objects
  579.         final TreeMap<PooledObject<T>, K> map = new TreeMap<>();

  580.         // Each item into the map using the PooledObject object as the
  581.         // key. It then gets sorted based on the idle time
  582.         poolMap.forEach((key, value) -> value.getIdleObjects().forEach(p -> map.put(p, key)));

  583.         // Now iterate created map and kill the first 15% plus one to account
  584.         // for zero
  585.         int itemsToRemove = (int) (map.size() * 0.15) + 1;
  586.         final Iterator<Entry<PooledObject<T>, K>> iter = map.entrySet().iterator();

  587.         while (iter.hasNext() && itemsToRemove > 0) {
  588.             final Entry<PooledObject<T>, K> entry = iter.next();
  589.             // kind of backwards on naming. In the map, each key is the
  590.             // PooledObject because it has the ordering with the timestamp
  591.             // value. Each value that the key references is the key of the
  592.             // list it belongs to.
  593.             final K key = entry.getValue();
  594.             final PooledObject<T> p = entry.getKey();
  595.             // Assume the destruction succeeds
  596.             boolean destroyed = true;
  597.             try {
  598.                 destroyed = destroy(key, p, false, DestroyMode.NORMAL);
  599.             } catch (final Exception e) {
  600.                 swallowException(e);
  601.             }
  602.             if (destroyed) {
  603.                 itemsToRemove--;
  604.             }
  605.         }
  606.     }

  607.     /**
  608.      * Closes the keyed object pool. Once the pool is closed,
  609.      * {@link #borrowObject(Object)} will fail with IllegalStateException, but
  610.      * {@link #returnObject(Object, Object)} and
  611.      * {@link #invalidateObject(Object, Object)} will continue to work, with
  612.      * returned objects destroyed on return.
  613.      * <p>
  614.      * Destroys idle instances in the pool by invoking {@link #clear()}.
  615.      * </p>
  616.      */
  617.     @Override
  618.     public void close() {
  619.         if (isClosed()) {
  620.             return;
  621.         }

  622.         synchronized (closeLock) {
  623.             if (isClosed()) {
  624.                 return;
  625.             }

  626.             // Stop the evictor before the pool is closed since evict() calls
  627.             // assertOpen()
  628.             stopEvictor();

  629.             closed = true;
  630.             // This clear removes any idle objects
  631.             clear();

  632.             jmxUnregister();

  633.             // Release any threads that were waiting for an object
  634.             poolMap.values().forEach(e -> e.getIdleObjects().interuptTakeWaiters());
  635.             // This clear cleans up the keys now any waiting threads have been
  636.             // interrupted
  637.             clear();
  638.         }
  639.     }

  640.     /**
  641.      * Creates a new pooled object or null.
  642.      *
  643.      * @param key Key associated with new pooled object.
  644.      * @return The new, wrapped pooled object. May return null.
  645.      * @throws Exception If the objection creation fails.
  646.      */
  647.     private PooledObject<T> create(final K key) throws Exception {
  648.         int maxTotalPerKeySave = getMaxTotalPerKey(); // Per key
  649.         if (maxTotalPerKeySave < 0) {
  650.             maxTotalPerKeySave = Integer.MAX_VALUE;
  651.         }
  652.         final int maxTotal = getMaxTotal();   // All keys

  653.         final ObjectDeque<T> objectDeque = poolMap.get(key);

  654.         // Check against the overall limit
  655.         boolean loop = true;

  656.         while (loop) {
  657.             final int newNumTotal = numTotal.incrementAndGet();
  658.             if (maxTotal > -1 && newNumTotal > maxTotal) {
  659.                 numTotal.decrementAndGet();
  660.                 if (getNumIdle() == 0) {
  661.                     return null;
  662.                 }
  663.                 clearOldest();
  664.             } else {
  665.                 loop = false;
  666.             }
  667.         }

  668.         // Flag that indicates if create should:
  669.         // - TRUE:  call the factory to create an object
  670.         // - FALSE: return null
  671.         // - null:  loop and re-test the condition that determines whether to
  672.         //          call the factory
  673.         Boolean create = null;
  674.         while (create == null) {
  675.             synchronized (objectDeque.makeObjectCountLock) {
  676.                 final long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
  677.                 // Check against the per key limit
  678.                 if (newCreateCount > maxTotalPerKeySave) {
  679.                     // The key is currently at capacity or in the process of
  680.                     // making enough new objects to take it to capacity.
  681.                     objectDeque.getCreateCount().decrementAndGet();
  682.                     if (objectDeque.makeObjectCount == 0) {
  683.                         // There are no makeObject() calls in progress for this
  684.                         // key so the key is at capacity. Do not attempt to
  685.                         // create a new object. Return and wait for an object to
  686.                         // be returned.
  687.                         create = Boolean.FALSE;
  688.                     } else {
  689.                         // There are makeObject() calls in progress that might
  690.                         // bring the pool to capacity. Those calls might also
  691.                         // fail so wait until they complete and then re-test if
  692.                         // the pool is at capacity or not.
  693.                         objectDeque.makeObjectCountLock.wait();
  694.                     }
  695.                 } else {
  696.                     // The pool is not at capacity. Create a new object.
  697.                     objectDeque.makeObjectCount++;
  698.                     create = Boolean.TRUE;
  699.                 }
  700.             }
  701.         }

  702.         if (!create.booleanValue()) {
  703.             numTotal.decrementAndGet();
  704.             return null;
  705.         }

  706.         PooledObject<T> p = null;
  707.         try {
  708.             p = factory.makeObject(key);
  709.             if (PooledObject.isNull(p)) {
  710.                 numTotal.decrementAndGet();
  711.                 objectDeque.getCreateCount().decrementAndGet();
  712.                 throw new NullPointerException(String.format("%s.makeObject() = null", factory.getClass().getSimpleName()));
  713.             }
  714.             if (getTestOnCreate() && !factory.validateObject(key, p)) {
  715.                 numTotal.decrementAndGet();
  716.                 objectDeque.getCreateCount().decrementAndGet();
  717.                 return null;
  718.             }
  719.         } catch (final Exception e) {
  720.             numTotal.decrementAndGet();
  721.             objectDeque.getCreateCount().decrementAndGet();
  722.             throw e;
  723.         } finally {
  724.             synchronized (objectDeque.makeObjectCountLock) {
  725.                 objectDeque.makeObjectCount--;
  726.                 objectDeque.makeObjectCountLock.notifyAll();
  727.             }
  728.         }

  729.         final AbandonedConfig ac = this.abandonedConfig;
  730.         if (ac != null && ac.getLogAbandoned()) {
  731.             p.setLogAbandoned(true);
  732.             p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
  733.         }

  734.         createdCount.incrementAndGet();
  735.         objectDeque.getAllObjects().put(new IdentityWrapper<>(p.getObject()), p);
  736.         return p;
  737.     }

  738.     /**
  739.      * De-register the use of a key by an object.
  740.      * <p>
  741.      * {@link #register(Object)} and {@link #deregister(Object)} must always be used as a pair.
  742.      * </p>
  743.      *
  744.      * @param k The key to de-register
  745.      */
  746.     private void deregister(final K k) {
  747.         Lock lock = keyLock.readLock();
  748.         try {
  749.             lock.lock();
  750.             ObjectDeque<T> objectDeque = poolMap.get(k);
  751.             if (objectDeque == null) {
  752.                 throw new IllegalStateException("Attempt to de-register a key for a non-existent pool");
  753.             }
  754.             final long numInterested = objectDeque.getNumInterested().decrementAndGet();
  755.             if (numInterested < 0) {
  756.                 throw new IllegalStateException("numInterested count for key " + k + " is less than zero");
  757.             }
  758.             if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
  759.                 // Potential to remove key
  760.                 // Upgrade to write lock
  761.                 lock.unlock();
  762.                 lock = keyLock.writeLock();
  763.                 lock.lock();
  764.                 // Pool may have changed since we released the read lock
  765.                 // numInterested decrement could lead to removal while waiting for write lock
  766.                 objectDeque = poolMap.get(k);
  767.                 if (null != objectDeque && objectDeque.getNumInterested().get() == 0 && objectDeque.getCreateCount().get() == 0) {
  768.                     // NOTE: Keys must always be removed from both poolMap and
  769.                     // poolKeyList at the same time while protected by
  770.                     // keyLock.writeLock()
  771.                     poolMap.remove(k);
  772.                     poolKeyList.remove(k);
  773.                 }
  774.             }
  775.         } finally {
  776.             lock.unlock();
  777.         }
  778.     }

  779.     /**
  780.      * Destroy the wrapped, pooled object.
  781.      *
  782.      * @param key The key associated with the object to destroy.
  783.      * @param toDestroy The wrapped object to be destroyed
  784.      * @param always Should the object be destroyed even if it is not currently
  785.      *               in the set of idle objects for the given key
  786.      * @param destroyMode DestroyMode context provided to the factory
  787.      * @return {@code true} if the object was destroyed, otherwise {@code false}
  788.      * @throws Exception If the object destruction failed
  789.      */
  790.     private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always, final DestroyMode destroyMode) throws Exception {

  791.         final ObjectDeque<T> objectDeque = register(key);

  792.         try {
  793.             boolean isIdle;
  794.             synchronized (toDestroy) {
  795.                 // Check idle state directly
  796.                 isIdle = toDestroy.getState().equals(PooledObjectState.IDLE);
  797.                 // If idle, not under eviction test, or always is true, remove instance,
  798.                 // updating isIdle if instance is found in idle objects
  799.                 if (isIdle || always) {
  800.                     isIdle = objectDeque.getIdleObjects().remove(toDestroy);
  801.                 }
  802.             }
  803.             if (isIdle || always) {
  804.                 objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject()));
  805.                 toDestroy.invalidate();

  806.                 try {
  807.                     factory.destroyObject(key, toDestroy, destroyMode);
  808.                 } finally {
  809.                     objectDeque.getCreateCount().decrementAndGet();
  810.                     destroyedCount.incrementAndGet();
  811.                     numTotal.decrementAndGet();
  812.                 }
  813.                 return true;
  814.             }
  815.             return false;
  816.         } finally {
  817.             deregister(key);
  818.         }
  819.     }

  820.     @Override
  821.     void ensureMinIdle() throws Exception {
  822.         final int minIdlePerKeySave = getMinIdlePerKey();
  823.         if (minIdlePerKeySave < 1) {
  824.             return;
  825.         }

  826.         for (final K k : poolMap.keySet()) {
  827.             ensureMinIdle(k);
  828.         }
  829.     }

  830.     /**
  831.      * Try to ensure that the configured number of minimum idle objects is available in
  832.      * the pool for the given key.
  833.      * <p>
  834.      * If there is no capacity available to add to the pool, this is a no-op
  835.      * (no exception, no impact to the pool).
  836.      * </p>
  837.      * <p>
  838.      * If the factory returns null when creating an object, a {@code NullPointerException}
  839.      * is thrown.
  840.      * </p>
  841.      *
  842.      * @param key The key to check for idle objects
  843.      * @throws Exception If a new object is required and cannot be created
  844.      */
  845.     private void ensureMinIdle(final K key) throws Exception {
  846.         // Calculate current pool objects
  847.         ObjectDeque<T> objectDeque = poolMap.get(key);

  848.         // objectDeque == null is OK here. It is handled correctly by both
  849.         // methods called below.

  850.         // this method isn't synchronized so the
  851.         // calculateDeficit is done at the beginning
  852.         // as a loop limit and a second time inside the loop
  853.         // to stop when another thread already returned the
  854.         // needed objects
  855.         final int deficit = calculateDeficit(objectDeque);

  856.         for (int i = 0; i < deficit && calculateDeficit(objectDeque) > 0; i++) {
  857.             addObject(key);
  858.             // If objectDeque was null, it won't be any more. Obtain a reference
  859.             // to it so the deficit can be correctly calculated. It needs to
  860.             // take account of objects created in other threads.
  861.             if (objectDeque == null) {
  862.                 objectDeque = poolMap.get(key);
  863.             }
  864.         }
  865.     }

  866.     /**
  867.      * {@inheritDoc}
  868.      * <p>
  869.      * Successive activations of this method examine objects in keyed sub-pools
  870.      * in sequence, cycling through the keys and examining objects in
  871.      * oldest-to-youngest order within the keyed sub-pools.
  872.      * </p>
  873.      */
  874.     @Override
  875.     public void evict() throws Exception {
  876.         assertOpen();

  877.         if (getNumIdle() > 0) {

  878.             PooledObject<T> underTest = null;
  879.             final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();

  880.             synchronized (evictionLock) {
  881.                 final EvictionConfig evictionConfig = new EvictionConfig(
  882.                         getMinEvictableIdleDuration(),
  883.                         getSoftMinEvictableIdleDuration(),
  884.                         getMinIdlePerKey());

  885.                 final boolean testWhileIdle = getTestWhileIdle();

  886.                 for (int i = 0, m = getNumTests(); i < m; i++) {
  887.                     if (evictionIterator == null || !evictionIterator.hasNext()) {
  888.                         if (evictionKeyIterator == null ||
  889.                                 !evictionKeyIterator.hasNext()) {
  890.                             final List<K> keyCopy = new ArrayList<>();
  891.                             final Lock readLock = keyLock.readLock();
  892.                             readLock.lock();
  893.                             try {
  894.                                 keyCopy.addAll(poolKeyList);
  895.                             } finally {
  896.                                 readLock.unlock();
  897.                             }
  898.                             evictionKeyIterator = keyCopy.iterator();
  899.                         }
  900.                         while (evictionKeyIterator.hasNext()) {
  901.                             evictionKey = evictionKeyIterator.next();
  902.                             final ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
  903.                             if (objectDeque == null) {
  904.                                 continue;
  905.                             }

  906.                             final Deque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
  907.                             evictionIterator = new EvictionIterator(idleObjects);
  908.                             if (evictionIterator.hasNext()) {
  909.                                 break;
  910.                             }
  911.                             evictionIterator = null;
  912.                         }
  913.                     }
  914.                     if (evictionIterator == null) {
  915.                         // Pools exhausted
  916.                         return;
  917.                     }
  918.                     final Deque<PooledObject<T>> idleObjects;
  919.                     try {
  920.                         underTest = evictionIterator.next();
  921.                         idleObjects = evictionIterator.getIdleObjects();
  922.                     } catch (final NoSuchElementException nsee) {
  923.                         // Object was borrowed in another thread
  924.                         // Don't count this as an eviction test so reduce i;
  925.                         i--;
  926.                         evictionIterator = null;
  927.                         continue;
  928.                     }

  929.                     if (!underTest.startEvictionTest()) {
  930.                         // Object was borrowed in another thread
  931.                         // Don't count this as an eviction test so reduce i;
  932.                         i--;
  933.                         continue;
  934.                     }

  935.                     // User provided eviction policy could throw all sorts of
  936.                     // crazy exceptions. Protect against such an exception
  937.                     // killing the eviction thread.
  938.                     boolean evict;
  939.                     try {
  940.                         evict = evictionPolicy.evict(evictionConfig, underTest,
  941.                                 poolMap.get(evictionKey).getIdleObjects().size());
  942.                     } catch (final Throwable t) {
  943.                         // Slightly convoluted as SwallowedExceptionListener
  944.                         // uses Exception rather than Throwable
  945.                         PoolUtils.checkRethrow(t);
  946.                         swallowException(new Exception(t));
  947.                         // Don't evict on error conditions
  948.                         evict = false;
  949.                     }

  950.                     if (evict) {
  951.                         destroy(evictionKey, underTest, true, DestroyMode.NORMAL);
  952.                         destroyedByEvictorCount.incrementAndGet();
  953.                     } else {
  954.                         if (testWhileIdle) {
  955.                             boolean active = false;
  956.                             try {
  957.                                 factory.activateObject(evictionKey, underTest);
  958.                                 active = true;
  959.                             } catch (final Exception e) {
  960.                                 destroy(evictionKey, underTest, true, DestroyMode.NORMAL);
  961.                                 destroyedByEvictorCount.incrementAndGet();
  962.                             }
  963.                             if (active) {
  964.                                 boolean validate = false;
  965.                                 Throwable validationThrowable = null;
  966.                                 try {
  967.                                     validate = factory.validateObject(evictionKey, underTest);
  968.                                 } catch (final Throwable t) {
  969.                                     PoolUtils.checkRethrow(t);
  970.                                     validationThrowable = t;
  971.                                 }
  972.                                 if (!validate) {
  973.                                     destroy(evictionKey, underTest, true, DestroyMode.NORMAL);
  974.                                     destroyedByEvictorCount.incrementAndGet();
  975.                                     if (validationThrowable != null) {
  976.                                         if (validationThrowable instanceof RuntimeException) {
  977.                                             throw (RuntimeException) validationThrowable;
  978.                                         }
  979.                                         throw (Error) validationThrowable;
  980.                                     }
  981.                                 } else {
  982.                                     try {
  983.                                         factory.passivateObject(evictionKey, underTest);
  984.                                     } catch (final Exception e) {
  985.                                         destroy(evictionKey, underTest, true, DestroyMode.NORMAL);
  986.                                         destroyedByEvictorCount.incrementAndGet();
  987.                                     }
  988.                                 }
  989.                             }
  990.                         }
  991.                         underTest.endEvictionTest(idleObjects);
  992.                         // TODO - May need to add code here once additional
  993.                         // states are used
  994.                     }
  995.                 }
  996.             }
  997.         }
  998.         final AbandonedConfig ac = this.abandonedConfig;
  999.         if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
  1000.             removeAbandoned(ac);
  1001.         }
  1002.     }

  1003.     /**
  1004.      * Gets a reference to the factory used to create, destroy and validate
  1005.      * the objects used by this pool.
  1006.      *
  1007.      * @return the factory
  1008.      */
  1009.     public KeyedPooledObjectFactory<K, T> getFactory() {
  1010.         return factory;
  1011.     }

  1012.     /**
  1013.      * Gets a copy of the pool key list.
  1014.      *
  1015.      * @return a copy of the pool key list.
  1016.      * @since 2.12.0
  1017.      */
  1018.     @Override
  1019.     @SuppressWarnings("unchecked")
  1020.     public List<K> getKeys() {
  1021.         return (List<K>) poolKeyList.clone();
  1022.     }

  1023.     /**
  1024.      * Gets the cap on the number of "idle" instances per key in the pool.
  1025.      * If maxIdlePerKey is set too low on heavily loaded systems it is possible
  1026.      * you will see objects being destroyed and almost immediately new objects
  1027.      * being created. This is a result of the active threads momentarily
  1028.      * returning objects faster than they are requesting them, causing the
  1029.      * number of idle objects to rise above maxIdlePerKey. The best value for
  1030.      * maxIdlePerKey for heavily loaded system will vary but the default is a
  1031.      * good starting point.
  1032.      *
  1033.      * @return the maximum number of "idle" instances that can be held in a
  1034.      *         given keyed sub-pool or a negative value if there is no limit
  1035.      *
  1036.      * @see #setMaxIdlePerKey
  1037.      */
  1038.     @Override
  1039.     public int getMaxIdlePerKey() {
  1040.         return maxIdlePerKey;
  1041.     }

  1042.     /**
  1043.      * Gets the limit on the number of object instances allocated by the pool
  1044.      * (checked out or idle), per key. When the limit is reached, the sub-pool
  1045.      * is said to be exhausted. A negative value indicates no limit.
  1046.      *
  1047.      * @return the limit on the number of active instances per key
  1048.      * @see #setMaxTotalPerKey
  1049.      */
  1050.     @Override
  1051.     public int getMaxTotalPerKey() {
  1052.         return maxTotalPerKey;
  1053.     }

  1054.     /**
  1055.      * Gets the target for the minimum number of idle objects to maintain in
  1056.      * each of the keyed sub-pools. This setting only has an effect if it is
  1057.      * positive and {@link #getDurationBetweenEvictionRuns()} is greater than
  1058.      * zero. If this is the case, an attempt is made to ensure that each
  1059.      * sub-pool has the required minimum number of instances during idle object
  1060.      * eviction runs.
  1061.      * <p>
  1062.      * If the configured value of minIdlePerKey is greater than the configured
  1063.      * value for maxIdlePerKey then the value of maxIdlePerKey will be used
  1064.      * instead.
  1065.      * </p>
  1066.      *
  1067.      * @return minimum size of the each keyed pool
  1068.      * @see #setTimeBetweenEvictionRunsMillis
  1069.      */
  1070.     @Override
  1071.     public int getMinIdlePerKey() {
  1072.         final int maxIdlePerKeySave = getMaxIdlePerKey();
  1073.         return Math.min(this.minIdlePerKey, maxIdlePerKeySave);
  1074.     }

  1075.     @Override
  1076.     public int getNumActive() {
  1077.         return numTotal.get() - getNumIdle();
  1078.     }

  1079.     @Override
  1080.     public int getNumActive(final K key) {
  1081.         final ObjectDeque<T> objectDeque = poolMap.get(key);
  1082.         if (objectDeque != null) {
  1083.             return objectDeque.getAllObjects().size() -
  1084.                     objectDeque.getIdleObjects().size();
  1085.         }
  1086.         return 0;
  1087.     }

  1088.     @Override
  1089.     public Map<String, Integer> getNumActivePerKey() {
  1090.         return poolMap.entrySet().stream().collect(Collectors.toMap(
  1091.                 e -> e.getKey().toString(),
  1092.                 e -> Integer.valueOf(e.getValue().getAllObjects().size() - e.getValue().getIdleObjects().size()),
  1093.                 (t, u) -> u));
  1094.     }

  1095.     @Override
  1096.     public int getNumIdle() {
  1097.         return poolMap.values().stream().mapToInt(e -> e.getIdleObjects().size()).sum();
  1098.     }

  1099.     @Override
  1100.     public int getNumIdle(final K key) {
  1101.         final ObjectDeque<T> objectDeque = poolMap.get(key);
  1102.         return objectDeque != null ? objectDeque.getIdleObjects().size() : 0;
  1103.     }

  1104.     /**
  1105.      * Gets the number of objects to test in a run of the idle object
  1106.      * evictor.
  1107.      *
  1108.      * @return The number of objects to test for validity
  1109.      */
  1110.     private int getNumTests() {
  1111.         final int totalIdle = getNumIdle();
  1112.         final int numTests = getNumTestsPerEvictionRun();
  1113.         if (numTests >= 0) {
  1114.             return Math.min(numTests, totalIdle);
  1115.         }
  1116.         return (int) Math.ceil(totalIdle / Math.abs((double) numTests));
  1117.     }

  1118.     /**
  1119.      * Gets an estimate of the number of threads currently blocked waiting for
  1120.      * an object from the pool. This is intended for monitoring only, not for
  1121.      * synchronization control.
  1122.      *
  1123.      * @return The estimate of the number of threads currently blocked waiting
  1124.      *         for an object from the pool
  1125.      */
  1126.     @Override
  1127.     public int getNumWaiters() {
  1128.         if (getBlockWhenExhausted()) {
  1129.             // Assume no overflow
  1130.             return poolMap.values().stream().mapToInt(e -> e.getIdleObjects().getTakeQueueLength()).sum();
  1131.         }
  1132.         return 0;
  1133.     }

  1134.     /**
  1135.      * Gets an estimate of the number of threads currently blocked waiting for
  1136.      * an object from the pool for each key. This is intended for
  1137.      * monitoring only, not for synchronization control.
  1138.      *
  1139.      * @return The estimate of the number of threads currently blocked waiting
  1140.      *         for an object from the pool for each key
  1141.      */
  1142.     @Override
  1143.     public Map<String, Integer> getNumWaitersByKey() {
  1144.         final Map<String, Integer> result = new HashMap<>();
  1145.         poolMap.forEach((k, deque) -> result.put(k.toString(), getBlockWhenExhausted() ?
  1146.                 Integer.valueOf(deque.getIdleObjects().getTakeQueueLength()) :
  1147.                 ZERO));
  1148.         return result;
  1149.     }

  1150.     @Override
  1151.     String getStatsString() {
  1152.         // Simply listed in AB order.
  1153.         return super.getStatsString() +
  1154.                 String.format(", fairness=%s, maxIdlePerKey%,d, maxTotalPerKey=%,d, minIdlePerKey=%,d, numTotal=%,d",
  1155.                         fairness, maxIdlePerKey, maxTotalPerKey, minIdlePerKey, numTotal.get());
  1156.     }

  1157.     /**
  1158.      * Tests to see if there are any threads currently waiting to borrow
  1159.      * objects but are blocked waiting for more objects to become available.
  1160.      *
  1161.      * @return {@code true} if there is at least one thread waiting otherwise
  1162.      *         {@code false}
  1163.      */
  1164.     private boolean hasBorrowWaiters() {
  1165.         return getBlockWhenExhausted() && poolMap.values().stream().anyMatch(deque -> deque.getIdleObjects().hasTakeWaiters());
  1166.     }

  1167.     /**
  1168.      * {@inheritDoc}
  1169.      * <p>
  1170.      * Activation of this method decrements the active count associated with
  1171.      * the given keyed pool and attempts to destroy {@code obj.}
  1172.      * </p>
  1173.      *
  1174.      * @param key pool key
  1175.      * @param obj instance to invalidate
  1176.      * @throws Exception             if an exception occurs destroying the
  1177.      *                               object
  1178.      * @throws IllegalStateException if obj does not belong to the pool
  1179.      *                               under the given key
  1180.      */
  1181.     @Override
  1182.     public void invalidateObject(final K key, final T obj) throws Exception {
  1183.         invalidateObject(key, obj, DestroyMode.NORMAL);
  1184.     }

  1185.     /**
  1186.      * {@inheritDoc}
  1187.      * <p>
  1188.      * Activation of this method decrements the active count associated with
  1189.      * the given keyed pool and attempts to destroy {@code obj.}
  1190.      * </p>
  1191.      *
  1192.      * @param key pool key
  1193.      * @param obj instance to invalidate
  1194.      * @param destroyMode DestroyMode context provided to factory
  1195.      * @throws Exception             if an exception occurs destroying the
  1196.      *                               object
  1197.      * @throws IllegalStateException if obj does not belong to the pool
  1198.      *                               under the given key
  1199.      * @since 2.9.0
  1200.      */
  1201.     @Override
  1202.     public void invalidateObject(final K key, final T obj, final DestroyMode destroyMode) throws Exception {
  1203.         final ObjectDeque<T> objectDeque = poolMap.get(key);
  1204.         final PooledObject<T> p = objectDeque != null ? objectDeque.getAllObjects().get(new IdentityWrapper<>(obj)) : null;
  1205.         if (p == null) {
  1206.             throw new IllegalStateException(appendStats("Object not currently part of this pool"));
  1207.         }
  1208.         synchronized (p) {
  1209.             if (p.getState() != PooledObjectState.INVALID) {
  1210.                 destroy(key, p, true, destroyMode);
  1211.                 reuseCapacity();
  1212.             }
  1213.         }
  1214.     }

  1215.     /**
  1216.      * Provides information on all the objects in the pool, both idle (waiting
  1217.      * to be borrowed) and active (currently borrowed).
  1218.      * <p>
  1219.      * Note: This is named listAllObjects so it is presented as an operation via
  1220.      * JMX. That means it won't be invoked unless the explicitly requested
  1221.      * whereas all attributes will be automatically requested when viewing the
  1222.      * attributes for an object in a tool like JConsole.
  1223.      * </p>
  1224.      *
  1225.      * @return Information grouped by key on all the objects in the pool
  1226.      */
  1227.     @Override
  1228.     public Map<String, List<DefaultPooledObjectInfo>> listAllObjects() {
  1229.         return poolMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toString(),
  1230.                 e -> e.getValue().getAllObjects().values().stream().map(DefaultPooledObjectInfo::new).collect(Collectors.toList())));
  1231.     }

  1232.     /**
  1233.      * Registers a key for pool control and ensures that
  1234.      * {@link #getMinIdlePerKey()} idle instances are created.
  1235.      *
  1236.      * @param key   The key to register for pool control.
  1237.      * @throws Exception If the associated factory throws an exception
  1238.      */
  1239.     public void preparePool(final K key) throws Exception {
  1240.         final int minIdlePerKeySave = getMinIdlePerKey();
  1241.         if (minIdlePerKeySave < 1) {
  1242.             return;
  1243.         }
  1244.         ensureMinIdle(key);
  1245.     }

  1246.     /**
  1247.      * Register the use of a key by an object.
  1248.      * <p>
  1249.      * {@link #register(Object)} and {@link #deregister(Object)} must always be used as a pair.
  1250.      * </p>
  1251.      *
  1252.      * @param k The key to register
  1253.      * @return The objects currently associated with the given key. If this
  1254.      *         method returns without throwing an exception then it will never
  1255.      *         return null.
  1256.      */
  1257.     private ObjectDeque<T> register(final K k) {
  1258.         Lock lock = keyLock.readLock();
  1259.         ObjectDeque<T> objectDeque = null;
  1260.         try {
  1261.             lock.lock();
  1262.             objectDeque = poolMap.get(k);
  1263.             if (objectDeque == null) {
  1264.                 // Upgrade to write lock
  1265.                 lock.unlock();
  1266.                 lock = keyLock.writeLock();
  1267.                 lock.lock();
  1268.                 final AtomicBoolean allocated = new AtomicBoolean();
  1269.                 objectDeque = poolMap.computeIfAbsent(k, key -> {
  1270.                     allocated.set(true);
  1271.                     final ObjectDeque<T> deque = new ObjectDeque<>(fairness);
  1272.                     deque.getNumInterested().incrementAndGet();
  1273.                     // NOTE: Keys must always be added to both poolMap and
  1274.                     //       poolKeyList at the same time while protected by
  1275.                     //       the write lock
  1276.                     poolKeyList.add(k);
  1277.                     return deque;
  1278.                 });
  1279.                 if (!allocated.get()) {
  1280.                     // Another thread could have beaten us to creating the deque, while we were
  1281.                     // waiting for the write lock, so re-get it from the map.
  1282.                     objectDeque = poolMap.get(k);
  1283.                     objectDeque.getNumInterested().incrementAndGet();
  1284.                 }
  1285.             } else {
  1286.                 objectDeque.getNumInterested().incrementAndGet();
  1287.             }
  1288.         } finally {
  1289.             lock.unlock();
  1290.         }
  1291.         return objectDeque;
  1292.     }

  1293.     /**
  1294.      * Recovers abandoned objects which have been checked out but
  1295.      * not used since longer than the removeAbandonedTimeout.
  1296.      *
  1297.      * @param abandonedConfig The configuration to use to identify abandoned objects
  1298.      */
  1299.     @SuppressWarnings("resource") // The PrintWriter is managed elsewhere
  1300.     private void removeAbandoned(final AbandonedConfig abandonedConfig) {
  1301.         poolMap.forEach((key, value) -> {
  1302.             // Generate a list of abandoned objects to remove
  1303.             final ArrayList<PooledObject<T>> remove = createRemoveList(abandonedConfig, value.getAllObjects());
  1304.             // Now remove the abandoned objects
  1305.             remove.forEach(pooledObject -> {
  1306.                 if (abandonedConfig.getLogAbandoned()) {
  1307.                     pooledObject.printStackTrace(abandonedConfig.getLogWriter());
  1308.                 }
  1309.                 try {
  1310.                     invalidateObject(key, pooledObject.getObject(), DestroyMode.ABANDONED);
  1311.                 } catch (final Exception e) {
  1312.                     swallowException(e);
  1313.                 }
  1314.             });
  1315.         });
  1316.     }

  1317.     /**
  1318.      * Returns an object to a keyed sub-pool.
  1319.      * <p>
  1320.      * If {@link #getMaxIdlePerKey() maxIdle} is set to a positive value and the
  1321.      * number of idle instances under the given key has reached this value, the
  1322.      * returning instance is destroyed.
  1323.      * </p>
  1324.      * <p>
  1325.      * If {@link #getTestOnReturn() testOnReturn} == true, the returning
  1326.      * instance is validated before being returned to the idle instance sub-pool
  1327.      * under the given key. In this case, if validation fails, the instance is
  1328.      * destroyed.
  1329.      * </p>
  1330.      * <p>
  1331.      * Exceptions encountered destroying objects for any reason are swallowed
  1332.      * but notified via a {@link SwallowedExceptionListener}.
  1333.      * </p>
  1334.      *
  1335.      * @param key pool key
  1336.      * @param obj instance to return to the keyed pool
  1337.      * @throws IllegalStateException if an object is returned to the pool that
  1338.      *                               was not borrowed from it or if an object is
  1339.      *                               returned to the pool multiple times
  1340.      */
  1341.     @Override
  1342.     public void returnObject(final K key, final T obj) {

  1343.         final ObjectDeque<T> objectDeque = poolMap.get(key);

  1344.         if (objectDeque == null) {
  1345.             throw new IllegalStateException("No keyed pool found under the given key.");
  1346.         }

  1347.         final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));

  1348.         if (PooledObject.isNull(p)) {
  1349.             throw new IllegalStateException("Returned object not currently part of this pool");
  1350.         }

  1351.         markReturningState(p);

  1352.         final Duration activeTime = p.getActiveDuration();

  1353.         try {
  1354.             if (getTestOnReturn() && !factory.validateObject(key, p)) {
  1355.                 try {
  1356.                     destroy(key, p, true, DestroyMode.NORMAL);
  1357.                 } catch (final Exception e) {
  1358.                     swallowException(e);
  1359.                 }
  1360.                 whenWaitersAddObject(key, objectDeque.idleObjects);
  1361.                 return;
  1362.             }

  1363.             try {
  1364.                 factory.passivateObject(key, p);
  1365.             } catch (final Exception e1) {
  1366.                 swallowException(e1);
  1367.                 try {
  1368.                     destroy(key, p, true, DestroyMode.NORMAL);
  1369.                 } catch (final Exception e) {
  1370.                     swallowException(e);
  1371.                 }
  1372.                 whenWaitersAddObject(key, objectDeque.idleObjects);
  1373.                 return;
  1374.             }

  1375.             if (!p.deallocate()) {
  1376.                 throw new IllegalStateException("Object has already been returned to this pool");
  1377.             }

  1378.             final int maxIdle = getMaxIdlePerKey();
  1379.             final LinkedBlockingDeque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();

  1380.             if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
  1381.                 try {
  1382.                     destroy(key, p, true, DestroyMode.NORMAL);
  1383.                 } catch (final Exception e) {
  1384.                     swallowException(e);
  1385.                 }
  1386.             } else {
  1387.                 if (getLifo()) {
  1388.                     idleObjects.addFirst(p);
  1389.                 } else {
  1390.                     idleObjects.addLast(p);
  1391.                 }
  1392.                 if (isClosed()) {
  1393.                     // Pool closed while object was being added to idle objects.
  1394.                     // Make sure the returned object is destroyed rather than left
  1395.                     // in the idle object pool (which would effectively be a leak)
  1396.                     clear(key);
  1397.                 }
  1398.             }
  1399.         } finally {
  1400.             if (hasBorrowWaiters()) {
  1401.                 reuseCapacity();
  1402.             }
  1403.             updateStatsReturn(activeTime);
  1404.         }
  1405.     }

  1406.     /**
  1407.      * Attempt to create one new instance to serve from the most heavily
  1408.      * loaded pool that can add a new instance.
  1409.      *
  1410.      * This method exists to ensure liveness in the pool when threads are
  1411.      * parked waiting and capacity to create instances under the requested keys
  1412.      * subsequently becomes available.
  1413.      *
  1414.      * This method is not guaranteed to create an instance and its selection
  1415.      * of the most loaded pool that can create an instance may not always be
  1416.      * correct, since it does not lock the pool and instances may be created,
  1417.      * borrowed, returned or destroyed by other threads while it is executing.
  1418.      */
  1419.     private void reuseCapacity() {
  1420.         final int maxTotalPerKeySave = getMaxTotalPerKey();
  1421.         int maxQueueLength = 0;
  1422.         LinkedBlockingDeque<PooledObject<T>> mostLoadedPool = null;
  1423.         K mostLoadedKey = null;

  1424.         // Find the most loaded pool that could take a new instance
  1425.         for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
  1426.             final K k = entry.getKey();
  1427.             final LinkedBlockingDeque<PooledObject<T>> pool = entry.getValue().getIdleObjects();
  1428.             final int queueLength = pool.getTakeQueueLength();
  1429.             if (getNumActive(k) < maxTotalPerKeySave && queueLength > maxQueueLength) {
  1430.                 maxQueueLength = queueLength;
  1431.                 mostLoadedPool = pool;
  1432.                 mostLoadedKey = k;
  1433.             }
  1434.         }

  1435.         // Attempt to add an instance to the most loaded pool.
  1436.         if (mostLoadedPool != null) {
  1437.             register(mostLoadedKey);
  1438.             try {
  1439.                 // If there is no capacity to add, create will return null
  1440.                 // and addIdleObject will no-op.
  1441.                 addIdleObject(mostLoadedKey, create(mostLoadedKey));
  1442.             } catch (final Exception e) {
  1443.                 swallowException(e);
  1444.             } finally {
  1445.                 deregister(mostLoadedKey);
  1446.             }
  1447.         }
  1448.     }

  1449.     /**
  1450.      * Call {@link #reuseCapacity()} repeatedly.
  1451.      * <p>
  1452.      * Always activates {@link #reuseCapacity()} at least once.
  1453.      *
  1454.      * @param newCapacity number of new instances to attempt to create.
  1455.      */
  1456.     private void reuseCapacity(final int newCapacity) {
  1457.         final int bound = newCapacity < 1 ? 1 : newCapacity;
  1458.         for (int i = 0; i < bound; i++) {
  1459.             reuseCapacity();
  1460.         }
  1461.     }

  1462.     /**
  1463.      * Sets the configuration.
  1464.      *
  1465.      * @param conf the new configuration to use. This is used by value.
  1466.      * @see GenericKeyedObjectPoolConfig
  1467.      */
  1468.     public void setConfig(final GenericKeyedObjectPoolConfig<T> conf) {
  1469.         super.setConfig(conf);
  1470.         setMaxIdlePerKey(conf.getMaxIdlePerKey());
  1471.         setMaxTotalPerKey(conf.getMaxTotalPerKey());
  1472.         setMaxTotal(conf.getMaxTotal());
  1473.         setMinIdlePerKey(conf.getMinIdlePerKey());
  1474.     }

  1475.     /**
  1476.      * Sets the cap on the number of "idle" instances per key in the pool.
  1477.      * If maxIdlePerKey is set too low on heavily loaded systems it is possible
  1478.      * you will see objects being destroyed and almost immediately new objects
  1479.      * being created. This is a result of the active threads momentarily
  1480.      * returning objects faster than they are requesting them, causing the
  1481.      * number of idle objects to rise above maxIdlePerKey. The best value for
  1482.      * maxIdlePerKey for heavily loaded system will vary but the default is a
  1483.      * good starting point.
  1484.      *
  1485.      * @param maxIdlePerKey the maximum number of "idle" instances that can be
  1486.      *                      held in a given keyed sub-pool. Use a negative value
  1487.      *                      for no limit
  1488.      *
  1489.      * @see #getMaxIdlePerKey
  1490.      */
  1491.     public void setMaxIdlePerKey(final int maxIdlePerKey) {
  1492.         this.maxIdlePerKey = maxIdlePerKey;
  1493.     }

  1494.     /**
  1495.      * Sets the limit on the number of object instances allocated by the pool
  1496.      * (checked out or idle), per key. When the limit is reached, the sub-pool
  1497.      * is said to be exhausted. A negative value indicates no limit.
  1498.      *
  1499.      * @param maxTotalPerKey the limit on the number of active instances per key
  1500.      * @see #getMaxTotalPerKey
  1501.      */
  1502.     public void setMaxTotalPerKey(final int maxTotalPerKey) {
  1503.         this.maxTotalPerKey = maxTotalPerKey;
  1504.     }

  1505.     /**
  1506.      * Sets the target for the minimum number of idle objects to maintain in
  1507.      * each of the keyed sub-pools. This setting only has an effect if it is
  1508.      * positive and {@link #getDurationBetweenEvictionRuns()} is greater than
  1509.      * zero. If this is the case, an attempt is made to ensure that each
  1510.      * sub-pool has the required minimum number of instances during idle object
  1511.      * eviction runs.
  1512.      * <p>
  1513.      * If the configured value of minIdlePerKey is greater than the configured
  1514.      * value for maxIdlePerKey then the value of maxIdlePerKey will be used
  1515.      * instead.
  1516.      * </p>
  1517.      *
  1518.      * @param minIdlePerKey The minimum size of the each keyed pool
  1519.      * @see #getMinIdlePerKey()
  1520.      * @see #getMaxIdlePerKey()
  1521.      * @see #setDurationBetweenEvictionRuns(Duration)
  1522.      */
  1523.     public void setMinIdlePerKey(final int minIdlePerKey) {
  1524.         this.minIdlePerKey = minIdlePerKey;
  1525.     }

  1526.     @Override
  1527.     protected void toStringAppendFields(final StringBuilder builder) {
  1528.         super.toStringAppendFields(builder);
  1529.         builder.append(", maxIdlePerKey=");
  1530.         builder.append(maxIdlePerKey);
  1531.         builder.append(", minIdlePerKey=");
  1532.         builder.append(minIdlePerKey);
  1533.         builder.append(", maxTotalPerKey=");
  1534.         builder.append(maxTotalPerKey);
  1535.         builder.append(", factory=");
  1536.         builder.append(factory);
  1537.         builder.append(", fairness=");
  1538.         builder.append(fairness);
  1539.         builder.append(", poolMap=");
  1540.         builder.append(poolMap);
  1541.         builder.append(", poolKeyList=");
  1542.         builder.append(poolKeyList);
  1543.         builder.append(", keyLock=");
  1544.         builder.append(keyLock);
  1545.         builder.append(", numTotal=");
  1546.         builder.append(numTotal);
  1547.         builder.append(", evictionKeyIterator=");
  1548.         builder.append(evictionKeyIterator);
  1549.         builder.append(", evictionKey=");
  1550.         builder.append(evictionKey);
  1551.         builder.append(", abandonedConfig=");
  1552.         builder.append(abandonedConfig);
  1553.     }

  1554.     /**
  1555.      * @since 2.10.0
  1556.      */
  1557.     @Override
  1558.     public void use(final T pooledObject) {
  1559.         final AbandonedConfig abandonedCfg = this.abandonedConfig;
  1560.         if (abandonedCfg != null && abandonedCfg.getUseUsageTracking()) {
  1561.             poolMap.values().stream()
  1562.                 .map(pool -> pool.getAllObjects().get(new IdentityWrapper<>(pooledObject)))
  1563.                 .filter(Objects::nonNull)
  1564.                 .findFirst()
  1565.                 .ifPresent(PooledObject::use);
  1566.         }
  1567.     }

  1568.     /**
  1569.      * When there is at least one thread waiting on the given deque, try to add an instance to pool under the given key.
  1570.      * NOTE: there is no check that the key corresponds to the deque (it is assumed that the key was used to get the deque
  1571.      * from the poolMap)
  1572.      *
  1573.      * @param key pool key.
  1574.      * @param idleObjects deque backing the pool under the given key
  1575.      */
  1576.     private void whenWaitersAddObject(final K key, final LinkedBlockingDeque<PooledObject<T>> idleObjects) {
  1577.         if (idleObjects.hasTakeWaiters()) {
  1578.             try {
  1579.                 addObject(key);
  1580.             } catch (final Exception e) {
  1581.                 swallowException(e);
  1582.             }
  1583.         }
  1584.     }

  1585. }