PoolUtils.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;

  18. import java.util.Collection;
  19. import java.util.Collections;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Timer;
  24. import java.util.TimerTask;
  25. import java.util.concurrent.locks.ReentrantReadWriteLock;
  26. import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
  27. import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

  28. /**
  29.  * This class consists exclusively of static methods that operate on or return
  30.  * ObjectPool or KeyedObjectPool related interfaces.
  31.  *
  32.  * @since 2.0
  33.  */
  34. public final class PoolUtils {

  35.     /**
  36.      * Encapsulate the logic for when the next poolable object should be
  37.      * discarded. Each time update is called, the next time to shrink is
  38.      * recomputed, based on the float factor, number of idle instances in the
  39.      * pool and high water mark. Float factor is assumed to be between 0 and 1.
  40.      * Values closer to 1 cause less frequent erosion events. Erosion event
  41.      * timing also depends on numIdle. When this value is relatively high (close
  42.      * to previously established high water mark), erosion occurs more
  43.      * frequently.
  44.      */
  45.     private static final class ErodingFactor {
  46.         /** Determines frequency of "erosion" events */
  47.         private final float factor;

  48.         /** Time of next shrink event */
  49.         private transient volatile long nextShrinkMillis;

  50.         /** High water mark - largest numIdle encountered */
  51.         private transient volatile int idleHighWaterMark;

  52.         /**
  53.          * Creates a new ErodingFactor with the given erosion factor.
  54.          *
  55.          * @param factor
  56.          *            erosion factor
  57.          */
  58.         public ErodingFactor(final float factor) {
  59.             this.factor = factor;
  60.             nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor
  61.             idleHighWaterMark = 1;
  62.         }

  63.         /**
  64.          * Gets the time of the next erosion event.
  65.          *
  66.          * @return next shrink time
  67.          */
  68.         public long getNextShrink() {
  69.             return nextShrinkMillis;
  70.         }

  71.         /**
  72.          * {@inheritDoc}
  73.          */
  74.         @Override
  75.         public String toString() {
  76.             return "ErodingFactor{" + "factor=" + factor +
  77.                     ", idleHighWaterMark=" + idleHighWaterMark + '}';
  78.         }

  79.         /**
  80.          * Updates internal state using the supplied time and numIdle.
  81.          *
  82.          * @param nowMillis
  83.          *            current time
  84.          * @param numIdle
  85.          *            number of idle elements in the pool
  86.          */
  87.         public void update(final long nowMillis, final int numIdle) {
  88.             final int idle = Math.max(0, numIdle);
  89.             idleHighWaterMark = Math.max(idle, idleHighWaterMark);
  90.             final float maxInterval = 15f;
  91.             final float minutes = maxInterval +
  92.                     (1f - maxInterval) / idleHighWaterMark * idle;
  93.             nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
  94.         }
  95.     }
  96.     /**
  97.      * Decorates a keyed object pool, adding "eroding" behavior. Based on the
  98.      * configured erosion factor, objects returning to the pool
  99.      * may be invalidated instead of being added to idle capacity.
  100.      *
  101.      * @param <K> object pool key type
  102.      * @param <V> object pool value type
  103.      */
  104.     private static class ErodingKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {

  105.         /** Underlying pool */
  106.         private final KeyedObjectPool<K, V> keyedPool;

  107.         /** Erosion factor */
  108.         private final ErodingFactor erodingFactor;

  109.         /**
  110.          * Creates an ErodingObjectPool wrapping the given pool using the
  111.          * specified erosion factor.
  112.          *
  113.          * @param keyedPool
  114.          *            underlying pool - must not be null
  115.          * @param erodingFactor
  116.          *            erosion factor - determines the frequency of erosion
  117.          *            events
  118.          * @see #erodingFactor
  119.          */
  120.         protected ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
  121.                 final ErodingFactor erodingFactor) {
  122.             if (keyedPool == null) {
  123.                 throw new IllegalArgumentException(
  124.                         MSG_NULL_KEYED_POOL);
  125.             }
  126.             this.keyedPool = keyedPool;
  127.             this.erodingFactor = erodingFactor;
  128.         }

  129.         /**
  130.          * Creates an ErodingObjectPool wrapping the given pool using the
  131.          * specified erosion factor.
  132.          *
  133.          * @param keyedPool
  134.          *            underlying pool
  135.          * @param factor
  136.          *            erosion factor - determines the frequency of erosion
  137.          *            events
  138.          * @see #erodingFactor
  139.          */
  140.         public ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
  141.                 final float factor) {
  142.             this(keyedPool, new ErodingFactor(factor));
  143.         }

  144.         /**
  145.          * {@inheritDoc}
  146.          */
  147.         @Override
  148.         public void addObject(final K key) throws Exception {
  149.             keyedPool.addObject(key);
  150.         }

  151.         /**
  152.          * {@inheritDoc}
  153.          */
  154.         @Override
  155.         public V borrowObject(final K key) throws Exception {
  156.             return keyedPool.borrowObject(key);
  157.         }

  158.         /**
  159.          * {@inheritDoc}
  160.          */
  161.         @Override
  162.         public void clear() throws Exception {
  163.             keyedPool.clear();
  164.         }

  165.         /**
  166.          * {@inheritDoc}
  167.          */
  168.         @Override
  169.         public void clear(final K key) throws Exception {
  170.             keyedPool.clear(key);
  171.         }

  172.         /**
  173.          * {@inheritDoc}
  174.          */
  175.         @Override
  176.         public void close() {
  177.             try {
  178.                 keyedPool.close();
  179.             } catch (final Exception ignored) {
  180.                 // ignored
  181.             }
  182.         }

  183.         /**
  184.          * Gets the eroding factor for the given key
  185.          *
  186.          * @param key
  187.          *            key
  188.          * @return eroding factor for the given keyed pool
  189.          */
  190.         protected ErodingFactor getErodingFactor(final K key) {
  191.             return erodingFactor;
  192.         }

  193.         /**
  194.          * Gets the underlying pool
  195.          *
  196.          * @return the keyed pool that this ErodingKeyedObjectPool wraps
  197.          */
  198.         protected KeyedObjectPool<K, V> getKeyedPool() {
  199.             return keyedPool;
  200.         }

  201.         /**
  202.          * {@inheritDoc}
  203.          */
  204.         @Override
  205.         public List<K> getKeys() {
  206.             return keyedPool.getKeys();
  207.         }

  208.         /**
  209.          * {@inheritDoc}
  210.          */
  211.         @Override
  212.         public int getNumActive() {
  213.             return keyedPool.getNumActive();
  214.         }

  215.         /**
  216.          * {@inheritDoc}
  217.          */
  218.         @Override
  219.         public int getNumActive(final K key) {
  220.             return keyedPool.getNumActive(key);
  221.         }

  222.         /**
  223.          * {@inheritDoc}
  224.          */
  225.         @Override
  226.         public int getNumIdle() {
  227.             return keyedPool.getNumIdle();
  228.         }

  229.         /**
  230.          * {@inheritDoc}
  231.          */
  232.         @Override
  233.         public int getNumIdle(final K key) {
  234.             return keyedPool.getNumIdle(key);
  235.         }

  236.         /**
  237.          * {@inheritDoc}
  238.          */
  239.         @Override
  240.         public void invalidateObject(final K key, final V obj) {
  241.             try {
  242.                 keyedPool.invalidateObject(key, obj);
  243.             } catch (final Exception ignored) {
  244.                 // ignored
  245.             }
  246.         }

  247.         /**
  248.          * Returns obj to the pool, unless erosion is triggered, in which case
  249.          * obj is invalidated. Erosion is triggered when there are idle
  250.          * instances in the pool associated with the given key and more than the
  251.          * configured {@link #erodingFactor erosion factor} time has elapsed
  252.          * since the last returnObject activation.
  253.          *
  254.          * @param obj
  255.          *            object to return or invalidate
  256.          * @param key
  257.          *            key
  258.          * @see #erodingFactor
  259.          */
  260.         @Override
  261.         public void returnObject(final K key, final V obj) throws Exception {
  262.             boolean discard = false;
  263.             final long nowMillis = System.currentTimeMillis();
  264.             final ErodingFactor factor = getErodingFactor(key);
  265.             synchronized (keyedPool) {
  266.                 if (factor.getNextShrink() < nowMillis) {
  267.                     final int numIdle = getNumIdle(key);
  268.                     if (numIdle > 0) {
  269.                         discard = true;
  270.                     }

  271.                     factor.update(nowMillis, numIdle);
  272.                 }
  273.             }
  274.             try {
  275.                 if (discard) {
  276.                     keyedPool.invalidateObject(key, obj);
  277.                 } else {
  278.                     keyedPool.returnObject(key, obj);
  279.                 }
  280.             } catch (final Exception ignored) {
  281.                 // ignored
  282.             }
  283.         }

  284.         /**
  285.          * {@inheritDoc}
  286.          */
  287.         @Override
  288.         public String toString() {
  289.             return "ErodingKeyedObjectPool{" + "factor=" +
  290.                     erodingFactor + ", keyedPool=" + keyedPool + '}';
  291.         }
  292.     }

  293.     /**
  294.      * Decorates an object pool, adding "eroding" behavior. Based on the
  295.      * configured {@link #factor erosion factor}, objects returning to the pool
  296.      * may be invalidated instead of being added to idle capacity.
  297.      *
  298.      * @param <T> type of objects in the pool
  299.      */
  300.     private static final class ErodingObjectPool<T> implements ObjectPool<T> {

  301.         /** Underlying object pool */
  302.         private final ObjectPool<T> pool;

  303.         /** Erosion factor */
  304.         private final ErodingFactor factor;

  305.         /**
  306.          * Creates an ErodingObjectPool wrapping the given pool using the
  307.          * specified erosion factor.
  308.          *
  309.          * @param pool
  310.          *            underlying pool
  311.          * @param factor
  312.          *            erosion factor - determines the frequency of erosion
  313.          *            events
  314.          * @see #factor
  315.          */
  316.         public ErodingObjectPool(final ObjectPool<T> pool, final float factor) {
  317.             this.pool = pool;
  318.             this.factor = new ErodingFactor(factor);
  319.         }

  320.         /**
  321.          * {@inheritDoc}
  322.          */
  323.         @Override
  324.         public void addObject() throws Exception{
  325.             pool.addObject();
  326.         }

  327.         /**
  328.          * {@inheritDoc}
  329.          */
  330.         @Override
  331.         public T borrowObject() throws Exception {
  332.             return pool.borrowObject();
  333.         }

  334.         /**
  335.          * {@inheritDoc}
  336.          */
  337.         @Override
  338.         public void clear() throws Exception {
  339.             pool.clear();
  340.         }

  341.         /**
  342.          * {@inheritDoc}
  343.          */
  344.         @Override
  345.         public void close() {
  346.             try {
  347.                 pool.close();
  348.             } catch (final Exception ignored) {
  349.                 // ignored
  350.             }
  351.         }

  352.         /**
  353.          * {@inheritDoc}
  354.          */
  355.         @Override
  356.         public int getNumActive() {
  357.             return pool.getNumActive();
  358.         }

  359.         /**
  360.          * {@inheritDoc}
  361.          */
  362.         @Override
  363.         public int getNumIdle() {
  364.             return pool.getNumIdle();
  365.         }

  366.         /**
  367.          * {@inheritDoc}
  368.          */
  369.         @Override
  370.         public void invalidateObject(final T obj) {
  371.             try {
  372.                 pool.invalidateObject(obj);
  373.             } catch (final Exception ignored) {
  374.                 // ignored
  375.             }
  376.         }

  377.         /**
  378.          * Returns * Gets obj to the pool, unless erosion is triggered, in which case
  379.          * obj is invalidated. Erosion is triggered when there are idle
  380.          * instances in the pool and more than the {@link #factor erosion
  381.          * factor}-determined time has elapsed since the last returnObject
  382.          * activation.
  383.          *
  384.          * @param obj
  385.          *            object to return or invalidate
  386.          * @see #factor
  387.          */
  388.         @Override
  389.         public void returnObject(final T obj) {
  390.             boolean discard = false;
  391.             final long nowMillis = System.currentTimeMillis();
  392.             synchronized (pool) {
  393.                 if (factor.getNextShrink() < nowMillis) { // XXX: Pool 3: move test
  394.                                                     // out of sync block
  395.                     final int numIdle = pool.getNumIdle();
  396.                     if (numIdle > 0) {
  397.                         discard = true;
  398.                     }

  399.                     factor.update(nowMillis, numIdle);
  400.                 }
  401.             }
  402.             try {
  403.                 if (discard) {
  404.                     pool.invalidateObject(obj);
  405.                 } else {
  406.                     pool.returnObject(obj);
  407.                 }
  408.             } catch (final Exception ignored) {
  409.                 // ignored
  410.             }
  411.         }

  412.         /**
  413.          * {@inheritDoc}
  414.          */
  415.         @Override
  416.         public String toString() {
  417.             return "ErodingObjectPool{" + "factor=" + factor + ", pool=" +
  418.                     pool + '}';
  419.         }
  420.     }
  421.     /**
  422.      * Extends ErodingKeyedObjectPool to allow erosion to take place on a
  423.      * per-key basis. Timing of erosion events is tracked separately for
  424.      * separate keyed pools.
  425.      *
  426.      * @param <K> object pool key type
  427.      * @param <V> object pool value type
  428.      */
  429.     private static final class ErodingPerKeyKeyedObjectPool<K, V> extends ErodingKeyedObjectPool<K, V> {

  430.         /** Erosion factor - same for all pools */
  431.         private final float factor;

  432.         /** Map of ErodingFactor instances keyed on pool keys */
  433.         private final Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<>());

  434.         /**
  435.          * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed
  436.          * pool with the specified erosion factor.
  437.          *
  438.          * @param keyedPool
  439.          *            underlying keyed pool
  440.          * @param factor
  441.          *            erosion factor
  442.          */
  443.         public ErodingPerKeyKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
  444.             super(keyedPool, null);
  445.             this.factor = factor;
  446.         }

  447.         /**
  448.          * {@inheritDoc}
  449.          */
  450.         @Override
  451.         protected ErodingFactor getErodingFactor(final K key) {
  452.             // This may result in two ErodingFactors being created for a key
  453.             // since they are small and cheap this is okay.
  454.             return factors.computeIfAbsent(key, k -> new ErodingFactor(this.factor));
  455.         }

  456.         /**
  457.          * {@inheritDoc}
  458.          */
  459.         @SuppressWarnings("resource") // getKeyedPool(): ivar access
  460.         @Override
  461.         public String toString() {
  462.             return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor +
  463.                     ", keyedPool=" + getKeyedPool() + '}';
  464.         }
  465.     }
  466.     /**
  467.      * Timer task that adds objects to the pool until the number of idle
  468.      * instances for the given key reaches the configured minIdle. Note that
  469.      * this is not the same as the pool's minIdle setting.
  470.      *
  471.      * @param <K> object pool key type
  472.      * @param <V> object pool value type
  473.      */
  474.     private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends TimerTask {

  475.         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
  476.         private final int minIdle;

  477.         /** Key to ensure minIdle for */
  478.         private final K key;

  479.         /** Keyed object pool */
  480.         private final KeyedObjectPool<K, V> keyedPool;

  481.         /**
  482.          * Creates a new KeyedObjecPoolMinIdleTimerTask.
  483.          *
  484.          * @param keyedPool
  485.          *            keyed object pool
  486.          * @param key
  487.          *            key to ensure minimum number of idle instances
  488.          * @param minIdle
  489.          *            minimum number of idle instances
  490.          * @throws IllegalArgumentException
  491.          *             if the key is null
  492.          */
  493.         KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool<K, V> keyedPool,
  494.                 final K key, final int minIdle) throws IllegalArgumentException {
  495.             if (keyedPool == null) {
  496.                 throw new IllegalArgumentException(
  497.                         MSG_NULL_KEYED_POOL);
  498.             }
  499.             this.keyedPool = keyedPool;
  500.             this.key = key;
  501.             this.minIdle = minIdle;
  502.         }

  503.         /**
  504.          * {@inheritDoc}
  505.          */
  506.         @Override
  507.         public void run() {
  508.             boolean success = false;
  509.             try {
  510.                 if (keyedPool.getNumIdle(key) < minIdle) {
  511.                     keyedPool.addObject(key);
  512.                 }
  513.                 success = true;

  514.             } catch (final Exception e) {
  515.                 cancel();

  516.             } finally {
  517.                 // detect other types of Throwable and cancel this Timer
  518.                 if (!success) {
  519.                     cancel();
  520.                 }
  521.             }
  522.         }

  523.         /**
  524.          * {@inheritDoc}
  525.          */
  526.         @Override
  527.         public String toString() {
  528.             final StringBuilder sb = new StringBuilder();
  529.             sb.append("KeyedObjectPoolMinIdleTimerTask");
  530.             sb.append("{minIdle=").append(minIdle);
  531.             sb.append(", key=").append(key);
  532.             sb.append(", keyedPool=").append(keyedPool);
  533.             sb.append('}');
  534.             return sb.toString();
  535.         }
  536.     }
  537.     /**
  538.      * Timer task that adds objects to the pool until the number of idle
  539.      * instances reaches the configured minIdle. Note that this is not the same
  540.      * as the pool's minIdle setting.
  541.      *
  542.      * @param <T> type of objects in the pool
  543.      */
  544.     private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask {

  545.         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
  546.         private final int minIdle;

  547.         /** Object pool */
  548.         private final ObjectPool<T> pool;

  549.         /**
  550.          * Constructs a new ObjectPoolMinIdleTimerTask for the given pool with the
  551.          * given minIdle setting.
  552.          *
  553.          * @param pool
  554.          *            object pool
  555.          * @param minIdle
  556.          *            number of idle instances to maintain
  557.          * @throws IllegalArgumentException
  558.          *             if the pool is null
  559.          */
  560.         ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, final int minIdle)
  561.                 throws IllegalArgumentException {
  562.             if (pool == null) {
  563.                 throw new IllegalArgumentException(MSG_NULL_POOL);
  564.             }
  565.             this.pool = pool;
  566.             this.minIdle = minIdle;
  567.         }

  568.         /**
  569.          * {@inheritDoc}
  570.          */
  571.         @Override
  572.         public void run() {
  573.             boolean success = false;
  574.             try {
  575.                 if (pool.getNumIdle() < minIdle) {
  576.                     pool.addObject();
  577.                 }
  578.                 success = true;

  579.             } catch (final Exception e) {
  580.                 cancel();
  581.             } finally {
  582.                 // detect other types of Throwable and cancel this Timer
  583.                 if (!success) {
  584.                     cancel();
  585.                 }
  586.             }
  587.         }

  588.         /**
  589.          * {@inheritDoc}
  590.          */
  591.         @Override
  592.         public String toString() {
  593.             final StringBuilder sb = new StringBuilder();
  594.             sb.append("ObjectPoolMinIdleTimerTask");
  595.             sb.append("{minIdle=").append(minIdle);
  596.             sb.append(", pool=").append(pool);
  597.             sb.append('}');
  598.             return sb.toString();
  599.         }
  600.     }

  601.     /**
  602.      * A synchronized (thread-safe) KeyedObjectPool backed by the specified
  603.      * KeyedObjectPool.
  604.      * <p>
  605.      * <strong>Note:</strong> This should not be used on pool implementations that already
  606.      * provide proper synchronization such as the pools provided in the Commons
  607.      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
  608.      * objects to be returned before allowing another one to be borrowed with
  609.      * another layer of synchronization will cause liveliness issues or a
  610.      * deadlock.
  611.      * </p>
  612.      *
  613.      * @param <K> object pool key type
  614.      * @param <V> object pool value type
  615.      */
  616.     static final class SynchronizedKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {

  617.         /**
  618.          * Object whose monitor is used to synchronize methods on the wrapped
  619.          * pool.
  620.          */
  621.         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

  622.         /** Underlying object pool */
  623.         private final KeyedObjectPool<K, V> keyedPool;

  624.         /**
  625.          * Creates a new SynchronizedKeyedObjectPool wrapping the given pool
  626.          *
  627.          * @param keyedPool
  628.          *            KeyedObjectPool to wrap
  629.          * @throws IllegalArgumentException
  630.          *             if keyedPool is null
  631.          */
  632.         SynchronizedKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool)
  633.                 throws IllegalArgumentException {
  634.             if (keyedPool == null) {
  635.                 throw new IllegalArgumentException(
  636.                         MSG_NULL_KEYED_POOL);
  637.             }
  638.             this.keyedPool = keyedPool;
  639.         }

  640.         /**
  641.          * {@inheritDoc}
  642.          */
  643.         @Override
  644.         public void addObject(final K key) throws Exception {
  645.             final WriteLock writeLock = readWriteLock.writeLock();
  646.             writeLock.lock();
  647.             try {
  648.                 keyedPool.addObject(key);
  649.             } finally {
  650.                 writeLock.unlock();
  651.             }
  652.         }

  653.         /**
  654.          * {@inheritDoc}
  655.          */
  656.         @Override
  657.         public V borrowObject(final K key) throws Exception {
  658.             final WriteLock writeLock = readWriteLock.writeLock();
  659.             writeLock.lock();
  660.             try {
  661.                 return keyedPool.borrowObject(key);
  662.             } finally {
  663.                 writeLock.unlock();
  664.             }
  665.         }

  666.         /**
  667.          * {@inheritDoc}
  668.          */
  669.         @Override
  670.         public void clear() throws Exception {
  671.             final WriteLock writeLock = readWriteLock.writeLock();
  672.             writeLock.lock();
  673.             try {
  674.                 keyedPool.clear();
  675.             } finally {
  676.                 writeLock.unlock();
  677.             }
  678.         }

  679.         /**
  680.          * {@inheritDoc}
  681.          */
  682.         @Override
  683.         public void clear(final K key) throws Exception {
  684.             final WriteLock writeLock = readWriteLock.writeLock();
  685.             writeLock.lock();
  686.             try {
  687.                 keyedPool.clear(key);
  688.             } finally {
  689.                 writeLock.unlock();
  690.             }
  691.         }

  692.         /**
  693.          * {@inheritDoc}
  694.          */
  695.         @Override
  696.         public void close() {
  697.             final WriteLock writeLock = readWriteLock.writeLock();
  698.             writeLock.lock();
  699.             try {
  700.                 keyedPool.close();
  701.             } catch (final Exception ignored) {
  702.                 // ignored as of Pool 2
  703.             } finally {
  704.                 writeLock.unlock();
  705.             }
  706.         }

  707.         /**
  708.          * {@inheritDoc}
  709.          */
  710.         @Override
  711.         public List<K> getKeys() {
  712.             final ReadLock readLock = readWriteLock.readLock();
  713.             readLock.lock();
  714.             try {
  715.                 return keyedPool.getKeys();
  716.             } finally {
  717.                 readLock.unlock();
  718.             }
  719.         }

  720.         /**
  721.          * {@inheritDoc}
  722.          */
  723.         @Override
  724.         public int getNumActive() {
  725.             final ReadLock readLock = readWriteLock.readLock();
  726.             readLock.lock();
  727.             try {
  728.                 return keyedPool.getNumActive();
  729.             } finally {
  730.                 readLock.unlock();
  731.             }
  732.         }

  733.         /**
  734.          * {@inheritDoc}
  735.          */
  736.         @Override
  737.         public int getNumActive(final K key) {
  738.             final ReadLock readLock = readWriteLock.readLock();
  739.             readLock.lock();
  740.             try {
  741.                 return keyedPool.getNumActive(key);
  742.             } finally {
  743.                 readLock.unlock();
  744.             }
  745.         }

  746.         /**
  747.          * {@inheritDoc}
  748.          */
  749.         @Override
  750.         public int getNumIdle() {
  751.             final ReadLock readLock = readWriteLock.readLock();
  752.             readLock.lock();
  753.             try {
  754.                 return keyedPool.getNumIdle();
  755.             } finally {
  756.                 readLock.unlock();
  757.             }
  758.         }

  759.         /**
  760.          * {@inheritDoc}
  761.          */
  762.         @Override
  763.         public int getNumIdle(final K key) {
  764.             final ReadLock readLock = readWriteLock.readLock();
  765.             readLock.lock();
  766.             try {
  767.                 return keyedPool.getNumIdle(key);
  768.             } finally {
  769.                 readLock.unlock();
  770.             }
  771.         }

  772.         /**
  773.          * {@inheritDoc}
  774.          */
  775.         @Override
  776.         public void invalidateObject(final K key, final V obj) {
  777.             final WriteLock writeLock = readWriteLock.writeLock();
  778.             writeLock.lock();
  779.             try {
  780.                 keyedPool.invalidateObject(key, obj);
  781.             } catch (final Exception ignored) {
  782.                 // ignored as of Pool 2
  783.             } finally {
  784.                 writeLock.unlock();
  785.             }
  786.         }

  787.         /**
  788.          * {@inheritDoc}
  789.          */
  790.         @Override
  791.         public void returnObject(final K key, final V obj) {
  792.             final WriteLock writeLock = readWriteLock.writeLock();
  793.             writeLock.lock();
  794.             try {
  795.                 keyedPool.returnObject(key, obj);
  796.             } catch (final Exception ignored) {
  797.                 // ignored
  798.             } finally {
  799.                 writeLock.unlock();
  800.             }
  801.         }

  802.         /**
  803.          * {@inheritDoc}
  804.          */
  805.         @Override
  806.         public String toString() {
  807.             final StringBuilder sb = new StringBuilder();
  808.             sb.append("SynchronizedKeyedObjectPool");
  809.             sb.append("{keyedPool=").append(keyedPool);
  810.             sb.append('}');
  811.             return sb.toString();
  812.         }
  813.     }

  814.     /**
  815.      * A fully synchronized KeyedPooledObjectFactory that wraps a
  816.      * KeyedPooledObjectFactory and synchronizes access to the wrapped factory
  817.      * methods.
  818.      * <p>
  819.      * <strong>Note:</strong> This should not be used on pool implementations that already
  820.      * provide proper synchronization such as the pools provided in the Commons
  821.      * Pool library.
  822.      * </p>
  823.      *
  824.      * @param <K> pooled object factory key type
  825.      * @param <V> pooled object factory value type
  826.      */
  827.     private static final class SynchronizedKeyedPooledObjectFactory<K, V> implements KeyedPooledObjectFactory<K, V> {

  828.         /** Synchronization lock */
  829.         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();

  830.         /** Wrapped factory */
  831.         private final KeyedPooledObjectFactory<K, V> keyedFactory;

  832.         /**
  833.          * Creates a SynchronizedKeyedPooledObjectFactory wrapping the given
  834.          * factory.
  835.          *
  836.          * @param keyedFactory
  837.          *            underlying factory to wrap
  838.          * @throws IllegalArgumentException
  839.          *             if the factory is null
  840.          */
  841.         SynchronizedKeyedPooledObjectFactory(final KeyedPooledObjectFactory<K, V> keyedFactory) throws IllegalArgumentException {
  842.             if (keyedFactory == null) {
  843.                 throw new IllegalArgumentException(
  844.                         "keyedFactory must not be null.");
  845.             }
  846.             this.keyedFactory = keyedFactory;
  847.         }

  848.         /**
  849.          * {@inheritDoc}
  850.          */
  851.         @Override
  852.         public void activateObject(final K key, final PooledObject<V> p) throws Exception {
  853.             writeLock.lock();
  854.             try {
  855.                 keyedFactory.activateObject(key, p);
  856.             } finally {
  857.                 writeLock.unlock();
  858.             }
  859.         }

  860.         /**
  861.          * {@inheritDoc}
  862.          */
  863.         @Override
  864.         public void destroyObject(final K key, final PooledObject<V> p) throws Exception {
  865.             writeLock.lock();
  866.             try {
  867.                 keyedFactory.destroyObject(key, p);
  868.             } finally {
  869.                 writeLock.unlock();
  870.             }
  871.         }

  872.         /**
  873.          * {@inheritDoc}
  874.          */
  875.         @Override
  876.         public PooledObject<V> makeObject(final K key) throws Exception {
  877.             writeLock.lock();
  878.             try {
  879.                 return keyedFactory.makeObject(key);
  880.             } finally {
  881.                 writeLock.unlock();
  882.             }
  883.         }

  884.         /**
  885.          * {@inheritDoc}
  886.          */
  887.         @Override
  888.         public void passivateObject(final K key, final PooledObject<V> p) throws Exception {
  889.             writeLock.lock();
  890.             try {
  891.                 keyedFactory.passivateObject(key, p);
  892.             } finally {
  893.                 writeLock.unlock();
  894.             }
  895.         }

  896.         /**
  897.          * {@inheritDoc}
  898.          */
  899.         @Override
  900.         public String toString() {
  901.             final StringBuilder sb = new StringBuilder();
  902.             sb.append("SynchronizedKeyedPooledObjectFactory");
  903.             sb.append("{keyedFactory=").append(keyedFactory);
  904.             sb.append('}');
  905.             return sb.toString();
  906.         }

  907.         /**
  908.          * {@inheritDoc}
  909.          */
  910.         @Override
  911.         public boolean validateObject(final K key, final PooledObject<V> p) {
  912.             writeLock.lock();
  913.             try {
  914.                 return keyedFactory.validateObject(key, p);
  915.             } finally {
  916.                 writeLock.unlock();
  917.             }
  918.         }
  919.     }

  920.     /**
  921.      * A synchronized (thread-safe) ObjectPool backed by the specified
  922.      * ObjectPool.
  923.      * <p>
  924.      * <strong>Note:</strong> This should not be used on pool implementations that already
  925.      * provide proper synchronization such as the pools provided in the Commons
  926.      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
  927.      * objects to be returned before allowing another one to be borrowed with
  928.      * another layer of synchronization will cause liveliness issues or a
  929.      * deadlock.
  930.      * </p>
  931.      *
  932.      * @param <T> type of objects in the pool
  933.      */
  934.     private static final class SynchronizedObjectPool<T> implements ObjectPool<T> {

  935.         /**
  936.          * Object whose monitor is used to synchronize methods on the wrapped
  937.          * pool.
  938.          */
  939.         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

  940.         /** The underlying object pool */
  941.         private final ObjectPool<T> pool;

  942.         /**
  943.          * Creates a new SynchronizedObjectPool wrapping the given pool.
  944.          *
  945.          * @param pool
  946.          *            the ObjectPool to be "wrapped" in a synchronized
  947.          *            ObjectPool.
  948.          * @throws IllegalArgumentException
  949.          *             if the pool is null
  950.          */
  951.         SynchronizedObjectPool(final ObjectPool<T> pool)
  952.                 throws IllegalArgumentException {
  953.             if (pool == null) {
  954.                 throw new IllegalArgumentException(MSG_NULL_POOL);
  955.             }
  956.             this.pool = pool;
  957.         }

  958.         /**
  959.          * {@inheritDoc}
  960.          */
  961.         @Override
  962.         public void addObject() throws Exception {
  963.             final WriteLock writeLock = readWriteLock.writeLock();
  964.             writeLock.lock();
  965.             try {
  966.                 pool.addObject();
  967.             } finally {
  968.                 writeLock.unlock();
  969.             }
  970.         }

  971.         /**
  972.          * {@inheritDoc}
  973.          */
  974.         @Override
  975.         public T borrowObject() throws Exception {
  976.             final WriteLock writeLock = readWriteLock.writeLock();
  977.             writeLock.lock();
  978.             try {
  979.                 return pool.borrowObject();
  980.             } finally {
  981.                 writeLock.unlock();
  982.             }
  983.         }

  984.         /**
  985.          * {@inheritDoc}
  986.          */
  987.         @Override
  988.         public void clear() throws Exception {
  989.             final WriteLock writeLock = readWriteLock.writeLock();
  990.             writeLock.lock();
  991.             try {
  992.                 pool.clear();
  993.             } finally {
  994.                 writeLock.unlock();
  995.             }
  996.         }

  997.         /**
  998.          * {@inheritDoc}
  999.          */
  1000.         @Override
  1001.         public void close() {
  1002.             final WriteLock writeLock = readWriteLock.writeLock();
  1003.             writeLock.lock();
  1004.             try {
  1005.                 pool.close();
  1006.             } catch (final Exception ignored) {
  1007.                 // ignored as of Pool 2
  1008.             } finally {
  1009.                 writeLock.unlock();
  1010.             }
  1011.         }

  1012.         /**
  1013.          * {@inheritDoc}
  1014.          */
  1015.         @Override
  1016.         public int getNumActive() {
  1017.             final ReadLock readLock = readWriteLock.readLock();
  1018.             readLock.lock();
  1019.             try {
  1020.                 return pool.getNumActive();
  1021.             } finally {
  1022.                 readLock.unlock();
  1023.             }
  1024.         }

  1025.         /**
  1026.          * {@inheritDoc}
  1027.          */
  1028.         @Override
  1029.         public int getNumIdle() {
  1030.             final ReadLock readLock = readWriteLock.readLock();
  1031.             readLock.lock();
  1032.             try {
  1033.                 return pool.getNumIdle();
  1034.             } finally {
  1035.                 readLock.unlock();
  1036.             }
  1037.         }

  1038.         /**
  1039.          * {@inheritDoc}
  1040.          */
  1041.         @Override
  1042.         public void invalidateObject(final T obj) {
  1043.             final WriteLock writeLock = readWriteLock.writeLock();
  1044.             writeLock.lock();
  1045.             try {
  1046.                 pool.invalidateObject(obj);
  1047.             } catch (final Exception ignored) {
  1048.                 // ignored as of Pool 2
  1049.             } finally {
  1050.                 writeLock.unlock();
  1051.             }
  1052.         }

  1053.         /**
  1054.          * {@inheritDoc}
  1055.          */
  1056.         @Override
  1057.         public void returnObject(final T obj) {
  1058.             final WriteLock writeLock = readWriteLock.writeLock();
  1059.             writeLock.lock();
  1060.             try {
  1061.                 pool.returnObject(obj);
  1062.             } catch (final Exception ignored) {
  1063.                 // ignored as of Pool 2
  1064.             } finally {
  1065.                 writeLock.unlock();
  1066.             }
  1067.         }

  1068.         /**
  1069.          * {@inheritDoc}
  1070.          */
  1071.         @Override
  1072.         public String toString() {
  1073.             final StringBuilder sb = new StringBuilder();
  1074.             sb.append("SynchronizedObjectPool");
  1075.             sb.append("{pool=").append(pool);
  1076.             sb.append('}');
  1077.             return sb.toString();
  1078.         }
  1079.     }

  1080.     /**
  1081.      * A fully synchronized PooledObjectFactory that wraps a
  1082.      * PooledObjectFactory and synchronizes access to the wrapped factory
  1083.      * methods.
  1084.      * <p>
  1085.      * <strong>Note:</strong> This should not be used on pool implementations that already
  1086.      * provide proper synchronization such as the pools provided in the Commons
  1087.      * Pool library.
  1088.      * </p>
  1089.      *
  1090.      * @param <T> pooled object factory type
  1091.      */
  1092.     private static final class SynchronizedPooledObjectFactory<T> implements
  1093.             PooledObjectFactory<T> {

  1094.         /** Synchronization lock */
  1095.         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();

  1096.         /** Wrapped factory */
  1097.         private final PooledObjectFactory<T> factory;

  1098.         /**
  1099.          * Creates a SynchronizedPoolableObjectFactory wrapping the given
  1100.          * factory.
  1101.          *
  1102.          * @param factory
  1103.          *            underlying factory to wrap
  1104.          * @throws IllegalArgumentException
  1105.          *             if the factory is null
  1106.          */
  1107.         SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory)
  1108.                 throws IllegalArgumentException {
  1109.             if (factory == null) {
  1110.                 throw new IllegalArgumentException("factory must not be null.");
  1111.             }
  1112.             this.factory = factory;
  1113.         }

  1114.         /**
  1115.          * {@inheritDoc}
  1116.          */
  1117.         @Override
  1118.         public void activateObject(final PooledObject<T> p) throws Exception {
  1119.             writeLock.lock();
  1120.             try {
  1121.                 factory.activateObject(p);
  1122.             } finally {
  1123.                 writeLock.unlock();
  1124.             }
  1125.         }

  1126.         /**
  1127.          * {@inheritDoc}
  1128.          */
  1129.         @Override
  1130.         public void destroyObject(final PooledObject<T> p) throws Exception {
  1131.             writeLock.lock();
  1132.             try {
  1133.                 factory.destroyObject(p);
  1134.             } finally {
  1135.                 writeLock.unlock();
  1136.             }
  1137.         }

  1138.         /**
  1139.          * {@inheritDoc}
  1140.          */
  1141.         @Override
  1142.         public PooledObject<T> makeObject() throws Exception {
  1143.             writeLock.lock();
  1144.             try {
  1145.                 return factory.makeObject();
  1146.             } finally {
  1147.                 writeLock.unlock();
  1148.             }
  1149.         }

  1150.         /**
  1151.          * {@inheritDoc}
  1152.          */
  1153.         @Override
  1154.         public void passivateObject(final PooledObject<T> p) throws Exception {
  1155.             writeLock.lock();
  1156.             try {
  1157.                 factory.passivateObject(p);
  1158.             } finally {
  1159.                 writeLock.unlock();
  1160.             }
  1161.         }

  1162.         /**
  1163.          * {@inheritDoc}
  1164.          */
  1165.         @Override
  1166.         public String toString() {
  1167.             final StringBuilder sb = new StringBuilder();
  1168.             sb.append("SynchronizedPoolableObjectFactory");
  1169.             sb.append("{factory=").append(factory);
  1170.             sb.append('}');
  1171.             return sb.toString();
  1172.         }

  1173.         /**
  1174.          * {@inheritDoc}
  1175.          */
  1176.         @Override
  1177.         public boolean validateObject(final PooledObject<T> p) {
  1178.             writeLock.lock();
  1179.             try {
  1180.                 return factory.validateObject(p);
  1181.             } finally {
  1182.                 writeLock.unlock();
  1183.             }
  1184.         }
  1185.     }

  1186.     /**
  1187.      * Timer used to periodically check pools idle object count. Because a
  1188.      * {@link Timer} creates a {@link Thread}, an IODH is used.
  1189.      */
  1190.     static class TimerHolder {
  1191.         static final Timer MIN_IDLE_TIMER = new Timer(true);
  1192.     }

  1193.     private static final String MSG_FACTOR_NEGATIVE = "factor must be positive.";

  1194.     private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";

  1195.     static final String MSG_NULL_KEY = "key must not be null.";

  1196.     private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";

  1197.     static final String MSG_NULL_KEYS = "keys must not be null.";

  1198.     private static final String MSG_NULL_POOL = "pool must not be null.";

  1199.     /**
  1200.      * Periodically check the idle object count for each key in the
  1201.      * {@code Collection keys} in the keyedPool. At most one idle object will be
  1202.      * added per period.
  1203.      *
  1204.      * @param keyedPool
  1205.      *            the keyedPool to check periodically.
  1206.      * @param keys
  1207.      *            a collection of keys to check the idle object count.
  1208.      * @param minIdle
  1209.      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
  1210.      *            this then add an idle object.
  1211.      * @param periodMillis
  1212.      *            the frequency in milliseconds to check the number of idle objects in a
  1213.      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
  1214.      * @param <K> the type of the pool key
  1215.      * @param <V> the type of pool entries
  1216.      * @return a {@link Map} of key and {@link TimerTask} pairs that will
  1217.      *         periodically check the pools idle object count.
  1218.      * @throws IllegalArgumentException
  1219.      *             when {@code keyedPool}, {@code keys}, or any of the values in
  1220.      *             the collection is {@code null} or when {@code minIdle} is
  1221.      *             negative or when {@code period} isn't valid for
  1222.      *             {@link Timer#schedule(TimerTask, long, long)}.
  1223.      * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
  1224.      */
  1225.     public static <K, V> Map<K, TimerTask> checkMinIdle(
  1226.             final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys,
  1227.             final int minIdle, final long periodMillis)
  1228.             throws IllegalArgumentException {
  1229.         if (keys == null) {
  1230.             throw new IllegalArgumentException(MSG_NULL_KEYS);
  1231.         }
  1232.         final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
  1233.         keys.forEach(key -> tasks.put(key, checkMinIdle(keyedPool, key, minIdle, periodMillis)));
  1234.         return tasks;
  1235.     }

  1236.     /**
  1237.      * Periodically check the idle object count for the key in the keyedPool. At
  1238.      * most one idle object will be added per period. If there is an exception
  1239.      * when calling {@link KeyedObjectPool#addObject(Object)} then no more
  1240.      * checks for that key will be performed.
  1241.      *
  1242.      * @param keyedPool
  1243.      *            the keyedPool to check periodically.
  1244.      * @param key
  1245.      *            the key to check the idle count of.
  1246.      * @param minIdle
  1247.      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
  1248.      *            this then add an idle object.
  1249.      * @param periodMillis
  1250.      *            the frequency in milliseconds to check the number of idle objects in a
  1251.      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
  1252.      * @param <K> the type of the pool key
  1253.      * @param <V> the type of pool entries
  1254.      * @return the {@link TimerTask} that will periodically check the pools idle
  1255.      *         object count.
  1256.      * @throws IllegalArgumentException
  1257.      *             when {@code keyedPool}, {@code key} is {@code null} or
  1258.      *             when {@code minIdle} is negative or when {@code period} isn't
  1259.      *             valid for {@link Timer#schedule(TimerTask, long, long)}.
  1260.      */
  1261.     public static <K, V> TimerTask checkMinIdle(
  1262.             final KeyedObjectPool<K, V> keyedPool, final K key,
  1263.             final int minIdle, final long periodMillis)
  1264.             throws IllegalArgumentException {
  1265.         if (keyedPool == null) {
  1266.             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
  1267.         }
  1268.         if (key == null) {
  1269.             throw new IllegalArgumentException(MSG_NULL_KEY);
  1270.         }
  1271.         if (minIdle < 0) {
  1272.             throw new IllegalArgumentException(MSG_MIN_IDLE);
  1273.         }
  1274.         final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
  1275.                 keyedPool, key, minIdle);
  1276.         getMinIdleTimer().schedule(task, 0L, periodMillis);
  1277.         return task;
  1278.     }

  1279.     /**
  1280.      * Periodically check the idle object count for the pool. At most one idle
  1281.      * object will be added per period. If there is an exception when calling
  1282.      * {@link ObjectPool#addObject()} then no more checks will be performed.
  1283.      *
  1284.      * @param pool
  1285.      *            the pool to check periodically.
  1286.      * @param minIdle
  1287.      *            if the {@link ObjectPool#getNumIdle()} is less than this then
  1288.      *            add an idle object.
  1289.      * @param periodMillis
  1290.      *            the frequency in milliseconds to check the number of idle objects in a pool,
  1291.      *            see {@link Timer#schedule(TimerTask, long, long)}.
  1292.      * @param <T> the type of objects in the pool
  1293.      * @return the {@link TimerTask} that will periodically check the pools idle
  1294.      *         object count.
  1295.      * @throws IllegalArgumentException
  1296.      *             when {@code pool} is {@code null} or when {@code minIdle} is
  1297.      *             negative or when {@code period} isn't valid for
  1298.      *             {@link Timer#schedule(TimerTask, long, long)}
  1299.      */
  1300.     public static <T> TimerTask checkMinIdle(final ObjectPool<T> pool,
  1301.             final int minIdle, final long periodMillis)
  1302.             throws IllegalArgumentException {
  1303.         if (pool == null) {
  1304.             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
  1305.         }
  1306.         if (minIdle < 0) {
  1307.             throw new IllegalArgumentException(MSG_MIN_IDLE);
  1308.         }
  1309.         final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
  1310.         getMinIdleTimer().schedule(task, 0L, periodMillis);
  1311.         return task;
  1312.     }

  1313.     /**
  1314.      * Should the supplied Throwable be re-thrown (eg if it is an instance of
  1315.      * one of the Throwables that should never be swallowed). Used by the pool
  1316.      * error handling for operations that throw exceptions that normally need to
  1317.      * be ignored.
  1318.      *
  1319.      * @param t
  1320.      *            The Throwable to check
  1321.      * @throws ThreadDeath
  1322.      *             if that is passed in
  1323.      * @throws VirtualMachineError
  1324.      *             if that is passed in
  1325.      */
  1326.     public static void checkRethrow(final Throwable t) {
  1327.         if (t instanceof ThreadDeath) {
  1328.             throw (ThreadDeath) t;
  1329.         }
  1330.         if (t instanceof VirtualMachineError) {
  1331.             throw (VirtualMachineError) t;
  1332.         }
  1333.         // All other instances of Throwable will be silently swallowed
  1334.     }

  1335.     /**
  1336.      * Returns a pool that adaptively decreases its size when idle objects are
  1337.      * no longer needed. This is intended as an always thread-safe alternative
  1338.      * to using an idle object evictor provided by many pool implementations.
  1339.      * This is also an effective way to shrink FIFO ordered pools that
  1340.      * experience load spikes.
  1341.      *
  1342.      * @param keyedPool
  1343.      *            the KeyedObjectPool to be decorated so it shrinks its idle
  1344.      *            count when possible.
  1345.      * @param <K> the type of the pool key
  1346.      * @param <V> the type of pool entries
  1347.      * @throws IllegalArgumentException
  1348.      *             when {@code keyedPool} is {@code null}.
  1349.      * @return a pool that adaptively decreases its size when idle objects are
  1350.      *         no longer needed.
  1351.      * @see #erodingPool(KeyedObjectPool, float)
  1352.      * @see #erodingPool(KeyedObjectPool, float, boolean)
  1353.      */
  1354.     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool) {
  1355.         return erodingPool(keyedPool, 1f);
  1356.     }

  1357.     /**
  1358.      * Returns a pool that adaptively decreases its size when idle objects are
  1359.      * no longer needed. This is intended as an always thread-safe alternative
  1360.      * to using an idle object evictor provided by many pool implementations.
  1361.      * This is also an effective way to shrink FIFO ordered pools that
  1362.      * experience load spikes.
  1363.      * <p>
  1364.      * The factor parameter provides a mechanism to tweak the rate at which the
  1365.      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
  1366.      * try to shrink its size more often. Values greater than 1 cause the pool
  1367.      * to less frequently try to shrink its size.
  1368.      * </p>
  1369.      *
  1370.      * @param keyedPool
  1371.      *            the KeyedObjectPool to be decorated so it shrinks its idle
  1372.      *            count when possible.
  1373.      * @param factor
  1374.      *            a positive value to scale the rate at which the pool tries to
  1375.      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
  1376.      *            shrinks more aggressively. If 1 &lt; factor then the pool
  1377.      *            shrinks less aggressively.
  1378.      * @param <K> the type of the pool key
  1379.      * @param <V> the type of pool entries
  1380.      * @throws IllegalArgumentException
  1381.      *             when {@code keyedPool} is {@code null} or when {@code factor}
  1382.      *             is not positive.
  1383.      * @return a pool that adaptively decreases its size when idle objects are
  1384.      *         no longer needed.
  1385.      * @see #erodingPool(KeyedObjectPool, float, boolean)
  1386.      */
  1387.     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
  1388.         return erodingPool(keyedPool, factor, false);
  1389.     }

  1390.     /**
  1391.      * Returns a pool that adaptively decreases its size when idle objects are
  1392.      * no longer needed. This is intended as an always thread-safe alternative
  1393.      * to using an idle object evictor provided by many pool implementations.
  1394.      * This is also an effective way to shrink FIFO ordered pools that
  1395.      * experience load spikes.
  1396.      * <p>
  1397.      * The factor parameter provides a mechanism to tweak the rate at which the
  1398.      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
  1399.      * try to shrink its size more often. Values greater than 1 cause the pool
  1400.      * to less frequently try to shrink its size.
  1401.      * </p>
  1402.      * <p>
  1403.      * The perKey parameter determines if the pool shrinks on a whole pool basis
  1404.      * or a per key basis. When perKey is false, the keys do not have an effect
  1405.      * on the rate at which the pool tries to shrink its size. When perKey is
  1406.      * true, each key is shrunk independently.
  1407.      * </p>
  1408.      *
  1409.      * @param keyedPool
  1410.      *            the KeyedObjectPool to be decorated so it shrinks its idle
  1411.      *            count when possible.
  1412.      * @param factor
  1413.      *            a positive value to scale the rate at which the pool tries to
  1414.      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
  1415.      *            shrinks more aggressively. If 1 &lt; factor then the pool
  1416.      *            shrinks less aggressively.
  1417.      * @param perKey
  1418.      *            when true, each key is treated independently.
  1419.      * @param <K> the type of the pool key
  1420.      * @param <V> the type of pool entries
  1421.      * @throws IllegalArgumentException
  1422.      *             when {@code keyedPool} is {@code null} or when {@code factor}
  1423.      *             is not positive.
  1424.      * @return a pool that adaptively decreases its size when idle objects are
  1425.      *         no longer needed.
  1426.      * @see #erodingPool(KeyedObjectPool)
  1427.      * @see #erodingPool(KeyedObjectPool, float)
  1428.      */
  1429.     public static <K, V> KeyedObjectPool<K, V> erodingPool(
  1430.             final KeyedObjectPool<K, V> keyedPool, final float factor,
  1431.             final boolean perKey) {
  1432.         if (keyedPool == null) {
  1433.             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
  1434.         }
  1435.         if (factor <= 0f) {
  1436.             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
  1437.         }
  1438.         if (perKey) {
  1439.             return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
  1440.         }
  1441.         return new ErodingKeyedObjectPool<>(keyedPool, factor);
  1442.     }

  1443.     /**
  1444.      * Returns a pool that adaptively decreases its size when idle objects are
  1445.      * no longer needed. This is intended as an always thread-safe alternative
  1446.      * to using an idle object evictor provided by many pool implementations.
  1447.      * This is also an effective way to shrink FIFO ordered pools that
  1448.      * experience load spikes.
  1449.      *
  1450.      * @param pool
  1451.      *            the ObjectPool to be decorated so it shrinks its idle count
  1452.      *            when possible.
  1453.      * @param <T> the type of objects in the pool
  1454.      * @throws IllegalArgumentException
  1455.      *             when {@code pool} is {@code null}.
  1456.      * @return a pool that adaptively decreases its size when idle objects are
  1457.      *         no longer needed.
  1458.      * @see #erodingPool(ObjectPool, float)
  1459.      */
  1460.     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool) {
  1461.         return erodingPool(pool, 1f);
  1462.     }

  1463.     /**
  1464.      * Returns a pool that adaptively decreases its size when idle objects are
  1465.      * no longer needed. This is intended as an always thread-safe alternative
  1466.      * to using an idle object evictor provided by many pool implementations.
  1467.      * This is also an effective way to shrink FIFO ordered pools that
  1468.      * experience load spikes.
  1469.      * <p>
  1470.      * The factor parameter provides a mechanism to tweak the rate at which the
  1471.      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
  1472.      * try to shrink its size more often. Values greater than 1 cause the pool
  1473.      * to less frequently try to shrink its size.
  1474.      * </p>
  1475.      *
  1476.      * @param pool
  1477.      *            the ObjectPool to be decorated so it shrinks its idle count
  1478.      *            when possible.
  1479.      * @param factor
  1480.      *            a positive value to scale the rate at which the pool tries to
  1481.      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
  1482.      *            shrinks more aggressively. If 1 &lt; factor then the pool
  1483.      *            shrinks less aggressively.
  1484.      * @param <T> the type of objects in the pool
  1485.      * @throws IllegalArgumentException
  1486.      *             when {@code pool} is {@code null} or when {@code factor} is
  1487.      *             not positive.
  1488.      * @return a pool that adaptively decreases its size when idle objects are
  1489.      *         no longer needed.
  1490.      * @see #erodingPool(ObjectPool)
  1491.      */
  1492.     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool, final float factor) {
  1493.         if (pool == null) {
  1494.             throw new IllegalArgumentException(MSG_NULL_POOL);
  1495.         }
  1496.         if (factor <= 0f) {
  1497.             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
  1498.         }
  1499.         return new ErodingObjectPool<>(pool, factor);
  1500.     }

  1501.     /**
  1502.      * Gets the {@code Timer} for checking keyedPool's idle count.
  1503.      *
  1504.      * @return the {@link Timer} for checking keyedPool's idle count.
  1505.      */
  1506.     private static Timer getMinIdleTimer() {
  1507.         return TimerHolder.MIN_IDLE_TIMER;
  1508.     }

  1509.     /**
  1510.      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
  1511.      * each key in {@code keys} for {@code count} number of times. This has
  1512.      * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)}
  1513.      * for each key in the {@code keys} collection.
  1514.      *
  1515.      * @param keyedPool
  1516.      *            the keyedPool to prefill.
  1517.      * @param keys
  1518.      *            {@link Collection} of keys to add objects for.
  1519.      * @param count
  1520.      *            the number of idle objects to add for each {@code key}.
  1521.      * @param <K> the type of the pool key
  1522.      * @param <V> the type of pool entries
  1523.      * @throws Exception
  1524.      *             when {@link KeyedObjectPool#addObject(Object)} fails.
  1525.      * @throws IllegalArgumentException
  1526.      *             when {@code keyedPool}, {@code keys}, or any value in
  1527.      *             {@code keys} is {@code null}.
  1528.      * @see #prefill(KeyedObjectPool, Object, int)
  1529.      * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}.
  1530.      */
  1531.     @Deprecated
  1532.     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
  1533.             final Collection<K> keys, final int count) throws Exception,
  1534.             IllegalArgumentException {
  1535.         if (keys == null) {
  1536.             throw new IllegalArgumentException(MSG_NULL_KEYS);
  1537.         }
  1538.         keyedPool.addObjects(keys, count);
  1539.     }

  1540.     /**
  1541.      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
  1542.      * {@code key} {@code count} number of times.
  1543.      *
  1544.      * @param keyedPool
  1545.      *            the keyedPool to prefill.
  1546.      * @param key
  1547.      *            the key to add objects for.
  1548.      * @param count
  1549.      *            the number of idle objects to add for {@code key}.
  1550.      * @param <K> the type of the pool key
  1551.      * @param <V> the type of pool entries
  1552.      * @throws Exception
  1553.      *             when {@link KeyedObjectPool#addObject(Object)} fails.
  1554.      * @throws IllegalArgumentException
  1555.      *             when {@code keyedPool} or {@code key} is {@code null}.
  1556.      * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}.
  1557.      */
  1558.     @Deprecated
  1559.     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
  1560.             final K key, final int count) throws Exception,
  1561.             IllegalArgumentException {
  1562.         if (keyedPool == null) {
  1563.             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
  1564.         }
  1565.         keyedPool.addObjects(key, count);
  1566.     }

  1567.     /**
  1568.      * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number
  1569.      * of times.
  1570.      *
  1571.      * @param pool
  1572.      *            the pool to prefill.
  1573.      * @param count
  1574.      *            the number of idle objects to add.
  1575.      * @param <T> the type of objects in the pool
  1576.      * @throws Exception
  1577.      *             when {@link ObjectPool#addObject()} fails.
  1578.      * @throws IllegalArgumentException
  1579.      *             when {@code pool} is {@code null}.
  1580.      * @deprecated Use {@link ObjectPool#addObjects(int)}.
  1581.      */
  1582.     @Deprecated
  1583.     public static <T> void prefill(final ObjectPool<T> pool, final int count)
  1584.             throws Exception {
  1585.         if (pool == null) {
  1586.             throw new IllegalArgumentException(MSG_NULL_POOL);
  1587.         }
  1588.         pool.addObjects(count);
  1589.     }

  1590.     /**
  1591.      * Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
  1592.      * the specified KeyedPooledObjectFactory.
  1593.      *
  1594.      * @param keyedFactory
  1595.      *            the KeyedPooledObjectFactory to be "wrapped" in a
  1596.      *            synchronized KeyedPooledObjectFactory.
  1597.      * @param <K> the type of the pool key
  1598.      * @param <V> the type of pool entries
  1599.      * @return a synchronized view of the specified KeyedPooledObjectFactory.
  1600.      */
  1601.     public static <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory(
  1602.         final KeyedPooledObjectFactory<K, V> keyedFactory) {
  1603.         return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
  1604.     }

  1605.     /**
  1606.      * Returns a synchronized (thread-safe) KeyedObjectPool backed by the
  1607.      * specified KeyedObjectPool.
  1608.      * <p>
  1609.      * <strong>Note:</strong> This should not be used on pool implementations that already
  1610.      * provide proper synchronization such as the pools provided in the Commons
  1611.      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
  1612.      * objects to be returned before allowing another one to be borrowed with
  1613.      * another layer of synchronization will cause liveliness issues or a
  1614.      * deadlock.
  1615.      * </p>
  1616.      *
  1617.      * @param keyedPool
  1618.      *            the KeyedObjectPool to be "wrapped" in a synchronized
  1619.      *            KeyedObjectPool.
  1620.      * @param <K> the type of the pool key
  1621.      * @param <V> the type of pool entries
  1622.      * @return a synchronized view of the specified KeyedObjectPool.
  1623.      */
  1624.     public static <K, V> KeyedObjectPool<K, V> synchronizedPool(final KeyedObjectPool<K, V> keyedPool) {
  1625.         /*
  1626.          * assert !(keyedPool instanceof GenericKeyedObjectPool) :
  1627.          * "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool
  1628.          * instanceof StackKeyedObjectPool) :
  1629.          * "StackKeyedObjectPool is already thread-safe"; assert
  1630.          * !"org.apache.commons.pool.composite.CompositeKeyedObjectPool"
  1631.          * .equals(keyedPool.getClass().getName()) :
  1632.          * "CompositeKeyedObjectPools are already thread-safe";
  1633.          */
  1634.         return new SynchronizedKeyedObjectPool<>(keyedPool);
  1635.     }

  1636.     /**
  1637.      * Returns a synchronized (thread-safe) ObjectPool backed by the specified
  1638.      * ObjectPool.
  1639.      * <p>
  1640.      * <strong>Note:</strong> This should not be used on pool implementations that already
  1641.      * provide proper synchronization such as the pools provided in the Commons
  1642.      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
  1643.      * objects to be returned before allowing another one to be borrowed with
  1644.      * another layer of synchronization will cause liveliness issues or a
  1645.      * deadlock.
  1646.      * </p>
  1647.      *
  1648.      * @param <T> the type of objects in the pool
  1649.      * @param pool
  1650.      *            the ObjectPool to be "wrapped" in a synchronized ObjectPool.
  1651.      * @throws IllegalArgumentException
  1652.      *             when {@code pool} is {@code null}.
  1653.      * @return a synchronized view of the specified ObjectPool.
  1654.      */
  1655.     public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) {
  1656.         if (pool == null) {
  1657.             throw new IllegalArgumentException(MSG_NULL_POOL);
  1658.         }

  1659.         /*
  1660.          * assert !(pool instanceof GenericObjectPool) :
  1661.          * "GenericObjectPool is already thread-safe"; assert !(pool instanceof
  1662.          * SoftReferenceObjectPool) :
  1663.          * "SoftReferenceObjectPool is already thread-safe"; assert !(pool
  1664.          * instanceof StackObjectPool) :
  1665.          * "StackObjectPool is already thread-safe"; assert
  1666.          * !"org.apache.commons.pool.composite.CompositeObjectPool"
  1667.          * .equals(pool.getClass().getName()) :
  1668.          * "CompositeObjectPools are already thread-safe";
  1669.          */
  1670.         return new SynchronizedObjectPool<>(pool);
  1671.     }

  1672.     /**
  1673.      * Returns a synchronized (thread-safe) PooledObjectFactory backed by the
  1674.      * specified PooledObjectFactory.
  1675.      *
  1676.      * @param factory
  1677.      *            the PooledObjectFactory to be "wrapped" in a synchronized
  1678.      *            PooledObjectFactory.
  1679.      * @param <T> the type of objects in the pool
  1680.      * @return a synchronized view of the specified PooledObjectFactory.
  1681.      */
  1682.     public static <T> PooledObjectFactory<T> synchronizedPooledFactory(final PooledObjectFactory<T> factory) {
  1683.         return new SynchronizedPooledObjectFactory<>(factory);
  1684.     }

  1685.     /**
  1686.      * PoolUtils instances should NOT be constructed in standard programming.
  1687.      * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
  1688.      * This constructor is public to permit tools that require a JavaBean
  1689.      * instance to operate.
  1690.      */
  1691.     public PoolUtils() {
  1692.     }
  1693. }