View Javadoc
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    *      https://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  
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Timer;
25  import java.util.TimerTask;
26  import java.util.concurrent.locks.ReentrantLock;
27  import java.util.concurrent.locks.ReentrantReadWriteLock;
28  import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
29  import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
30  
31  /**
32   * This class consists exclusively of static methods that operate on or return
33   * ObjectPool or KeyedObjectPool related interfaces.
34   *
35   * @since 2.0
36   */
37  public final class PoolUtils {
38  
39      /**
40       * Encapsulate the logic for when the next poolable object should be
41       * discarded. Each time update is called, the next time to shrink is
42       * recomputed, based on the float factor, number of idle instances in the
43       * pool and high water mark. Float factor is assumed to be between 0 and 1.
44       * Values closer to 1 cause less frequent erosion events. Erosion event
45       * timing also depends on numIdle. When this value is relatively high (close
46       * to previously established high water mark), erosion occurs more
47       * frequently.
48       */
49      private static final class ErodingFactor {
50  
51          private static final float MAX_INTERVAL = 15f;
52  
53          /** Determines frequency of "erosion" events */
54          private final float factor;
55  
56          /** Time of next shrink event */
57          private transient volatile long nextShrinkMillis;
58  
59          /** High water mark - largest numIdle encountered */
60          private transient volatile int idleHighWaterMark = 1;
61  
62          private final ReentrantLock lock = new ReentrantLock();
63  
64          /**
65           * Creates a new ErodingFactor with the given erosion factor.
66           *
67           * @param factor
68           *            erosion factor
69           */
70          private ErodingFactor(final float factor) {
71              this.factor = factor;
72              nextShrinkMillis = System.currentTimeMillis() + (long) (90_0000 * factor); // now + 15 min * factor
73          }
74  
75          /**
76           * Gets the time of the next erosion event.
77           *
78           * @return next shrink time
79           */
80          private long getNextShrink() {
81              return nextShrinkMillis;
82          }
83  
84          /**
85           * {@inheritDoc}
86           */
87          @Override
88          public String toString() {
89              return "ErodingFactor{factor=" + factor +
90                      ", idleHighWaterMark=" + idleHighWaterMark + '}';
91          }
92  
93          /**
94           * Updates internal state using the supplied time and numIdle.
95           *
96           * @param nowMillis
97           *            current time
98           * @param numIdle
99           *            number of idle elements in the pool
100          */
101         public void update(final long nowMillis, final int numIdle) {
102             final int idle = Math.max(0, numIdle);
103             lock.lock();
104             try {
105                 idleHighWaterMark = Math.max(idle, idleHighWaterMark);
106                 final float minutes = MAX_INTERVAL + (1f - MAX_INTERVAL) / idleHighWaterMark * idle;
107                 nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
108             } finally {
109                 lock.unlock();
110             }
111         }
112     }
113     /**
114      * Decorates a keyed object pool, adding "eroding" behavior. Based on the
115      * configured erosion factor, objects returning to the pool
116      * may be invalidated instead of being added to idle capacity.
117      *
118      * @param <K> object pool key type
119      * @param <V> object pool value type
120      */
121     private static class ErodingKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
122 
123         /** Underlying pool */
124         private final KeyedObjectPool<K, V> keyedPool;
125 
126         /** Erosion factor */
127         private final 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 - must not be null
135          * @param erodingFactor
136          *            erosion factor - determines the frequency of erosion
137          *            events
138          * @see #erodingFactor
139          */
140         private ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
141                 final ErodingFactor erodingFactor) {
142             if (keyedPool == null) {
143                 throw new IllegalArgumentException(
144                         MSG_NULL_KEYED_POOL);
145             }
146             this.keyedPool = keyedPool;
147             this.erodingFactor = erodingFactor;
148         }
149 
150         /**
151          * Creates an ErodingObjectPool wrapping the given pool using the
152          * specified erosion factor.
153          *
154          * @param keyedPool
155          *            underlying pool
156          * @param factor
157          *            erosion factor - determines the frequency of erosion
158          *            events
159          * @see #erodingFactor
160          */
161         private ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
162                 final float factor) {
163             this(keyedPool, new ErodingFactor(factor));
164         }
165 
166         /**
167          * {@inheritDoc}
168          */
169         @Override
170         public void addObject(final K key) throws Exception {
171             keyedPool.addObject(key);
172         }
173 
174         /**
175          * {@inheritDoc}
176          */
177         @Override
178         public V borrowObject(final K key) throws Exception {
179             return keyedPool.borrowObject(key);
180         }
181 
182         /**
183          * {@inheritDoc}
184          */
185         @Override
186         public void clear() throws Exception {
187             keyedPool.clear();
188         }
189 
190         /**
191          * {@inheritDoc}
192          */
193         @Override
194         public void clear(final K key) throws Exception {
195             keyedPool.clear(key);
196         }
197 
198         /**
199          * {@inheritDoc}
200          */
201         @Override
202         public void close() {
203             try {
204                 keyedPool.close();
205             } catch (final Exception ignored) {
206                 // ignored
207             }
208         }
209 
210         /**
211          * Gets the eroding factor for the given key
212          *
213          * @param key
214          *            key
215          * @return eroding factor for the given keyed pool
216          */
217         protected ErodingFactor getErodingFactor(final K key) {
218             return erodingFactor;
219         }
220 
221         /**
222          * Gets the underlying pool
223          *
224          * @return the keyed pool that this ErodingKeyedObjectPool wraps
225          */
226         protected KeyedObjectPool<K, V> getKeyedPool() {
227             return keyedPool;
228         }
229 
230         /**
231          * {@inheritDoc}
232          */
233         @Override
234         public List<K> getKeys() {
235             return keyedPool.getKeys();
236         }
237 
238         /**
239          * {@inheritDoc}
240          */
241         @Override
242         public int getNumActive() {
243             return keyedPool.getNumActive();
244         }
245 
246         /**
247          * {@inheritDoc}
248          */
249         @Override
250         public int getNumActive(final K key) {
251             return keyedPool.getNumActive(key);
252         }
253 
254         /**
255          * {@inheritDoc}
256          */
257         @Override
258         public int getNumIdle() {
259             return keyedPool.getNumIdle();
260         }
261 
262         /**
263          * {@inheritDoc}
264          */
265         @Override
266         public int getNumIdle(final K key) {
267             return keyedPool.getNumIdle(key);
268         }
269 
270         /**
271          * {@inheritDoc}
272          */
273         @Override
274         public void invalidateObject(final K key, final V obj) {
275             try {
276                 keyedPool.invalidateObject(key, obj);
277             } catch (final Exception ignored) {
278                 // ignored
279             }
280         }
281 
282         /**
283          * Returns obj to the pool, unless erosion is triggered, in which case
284          * obj is invalidated. Erosion is triggered when there are idle
285          * instances in the pool associated with the given key and more than the
286          * configured {@link #erodingFactor erosion factor} time has elapsed
287          * since the last returnObject activation.
288          *
289          * @param obj
290          *            object to return or invalidate
291          * @param key
292          *            key
293          * @see #erodingFactor
294          */
295         @Override
296         public void returnObject(final K key, final V obj) throws Exception {
297             boolean discard = false;
298             final long nowMillis = System.currentTimeMillis();
299             final ErodingFactor factor = getErodingFactor(key);
300             synchronized (keyedPool) {
301                 if (factor.getNextShrink() < nowMillis) {
302                     final int numIdle = getNumIdle(key);
303                     if (numIdle > 0) {
304                         discard = true;
305                     }
306 
307                     factor.update(nowMillis, numIdle);
308                 }
309             }
310             try {
311                 if (discard) {
312                     keyedPool.invalidateObject(key, obj);
313                 } else {
314                     keyedPool.returnObject(key, obj);
315                 }
316             } catch (final Exception ignored) {
317                 // ignored
318             }
319         }
320 
321         /**
322          * {@inheritDoc}
323          */
324         @Override
325         public String toString() {
326             return "ErodingKeyedObjectPool{factor=" +
327                     erodingFactor + ", keyedPool=" + keyedPool + '}';
328         }
329     }
330 
331     /**
332      * Decorates an object pool, adding "eroding" behavior. Based on the
333      * configured {@link #factor erosion factor}, objects returning to the pool
334      * may be invalidated instead of being added to idle capacity.
335      *
336      * @param <T> type of objects in the pool
337      */
338     private static final class ErodingObjectPool<T> implements ObjectPool<T> {
339 
340         /** Underlying object pool */
341         private final ObjectPool<T> pool;
342 
343         /** Erosion factor */
344         private final ErodingFactor factor;
345 
346         /**
347          * Creates an ErodingObjectPool wrapping the given pool using the
348          * specified erosion factor.
349          *
350          * @param pool
351          *            underlying pool
352          * @param factor
353          *            erosion factor - determines the frequency of erosion
354          *            events
355          * @see #factor
356          */
357         private ErodingObjectPool(final ObjectPool<T> pool, final float factor) {
358             this.pool = pool;
359             this.factor = new ErodingFactor(factor);
360         }
361 
362         /**
363          * {@inheritDoc}
364          */
365         @Override
366         public void addObject() throws Exception {
367             pool.addObject();
368         }
369 
370         /**
371          * {@inheritDoc}
372          */
373         @Override
374         public T borrowObject() throws Exception {
375             return pool.borrowObject();
376         }
377 
378         /**
379          * {@inheritDoc}
380          */
381         @Override
382         public void clear() throws Exception {
383             pool.clear();
384         }
385 
386         /**
387          * {@inheritDoc}
388          */
389         @Override
390         public void close() {
391             try {
392                 pool.close();
393             } catch (final Exception ignored) {
394                 // ignored
395             }
396         }
397 
398         /**
399          * {@inheritDoc}
400          */
401         @Override
402         public int getNumActive() {
403             return pool.getNumActive();
404         }
405 
406         /**
407          * {@inheritDoc}
408          */
409         @Override
410         public int getNumIdle() {
411             return pool.getNumIdle();
412         }
413 
414         /**
415          * {@inheritDoc}
416          */
417         @Override
418         public void invalidateObject(final T obj) {
419             try {
420                 pool.invalidateObject(obj);
421             } catch (final Exception ignored) {
422                 // ignored
423             }
424         }
425 
426         /**
427          * Returns * Gets obj to the pool, unless erosion is triggered, in which case
428          * obj is invalidated. Erosion is triggered when there are idle
429          * instances in the pool and more than the {@link #factor erosion
430          * factor}-determined time has elapsed since the last returnObject
431          * activation.
432          *
433          * @param obj
434          *            object to return or invalidate
435          * @see #factor
436          */
437         @Override
438         public void returnObject(final T obj) {
439             boolean discard = false;
440             final long nowMillis = System.currentTimeMillis();
441             synchronized (pool) {
442                 if (factor.getNextShrink() < nowMillis) { // XXX: Pool 3: move test
443                                                     // out of sync block
444                     final int numIdle = pool.getNumIdle();
445                     if (numIdle > 0) {
446                         discard = true;
447                     }
448 
449                     factor.update(nowMillis, numIdle);
450                 }
451             }
452             try {
453                 if (discard) {
454                     pool.invalidateObject(obj);
455                 } else {
456                     pool.returnObject(obj);
457                 }
458             } catch (final Exception ignored) {
459                 // ignored
460             }
461         }
462 
463         /**
464          * {@inheritDoc}
465          */
466         @Override
467         public String toString() {
468             return "ErodingObjectPool{factor=" + factor + ", pool=" +
469                     pool + '}';
470         }
471     }
472     /**
473      * Extends ErodingKeyedObjectPool to allow erosion to take place on a
474      * per-key basis. Timing of erosion events is tracked separately for
475      * separate keyed pools.
476      *
477      * @param <K> object pool key type
478      * @param <V> object pool value type
479      */
480     private static final class ErodingPerKeyKeyedObjectPool<K, V> extends ErodingKeyedObjectPool<K, V> {
481 
482         /** Erosion factor - same for all pools */
483         private final float factor;
484 
485         /** Map of ErodingFactor instances keyed on pool keys */
486         private final Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<>());
487 
488         /**
489          * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed
490          * pool with the specified erosion factor.
491          *
492          * @param keyedPool
493          *            underlying keyed pool
494          * @param factor
495          *            erosion factor
496          */
497         private ErodingPerKeyKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
498             super(keyedPool, null);
499             this.factor = factor;
500         }
501 
502         /**
503          * {@inheritDoc}
504          */
505         @Override
506         protected ErodingFactor getErodingFactor(final K key) {
507             // This may result in two ErodingFactors being created for a key
508             // since they are small and cheap this is okay.
509             return factors.computeIfAbsent(key, k -> new ErodingFactor(this.factor));
510         }
511 
512         /**
513          * {@inheritDoc}
514          */
515         @SuppressWarnings("resource") // getKeyedPool(): ivar access
516         @Override
517         public String toString() {
518             return "ErodingPerKeyKeyedObjectPool{factor=" + factor +
519                     ", keyedPool=" + getKeyedPool() + '}';
520         }
521     }
522     /**
523      * Timer task that adds objects to the pool until the number of idle
524      * instances for the given key reaches the configured minIdle. Note that
525      * this is not the same as the pool's minIdle setting.
526      *
527      * @param <K> object pool key type
528      * @param <V> object pool value type
529      */
530     private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends TimerTask {
531 
532         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
533         private final int minIdle;
534 
535         /** Key to ensure minIdle for */
536         private final K key;
537 
538         /** Keyed object pool */
539         private final KeyedObjectPool<K, V> keyedPool;
540 
541         /**
542          * Creates a new KeyedObjecPoolMinIdleTimerTask.
543          *
544          * @param keyedPool
545          *            keyed object pool
546          * @param key
547          *            key to ensure minimum number of idle instances
548          * @param minIdle
549          *            minimum number of idle instances
550          * @throws IllegalArgumentException
551          *             if the key is null
552          */
553         KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool<K, V> keyedPool,
554                 final K key, final int minIdle) throws IllegalArgumentException {
555             if (keyedPool == null) {
556                 throw new IllegalArgumentException(
557                         MSG_NULL_KEYED_POOL);
558             }
559             this.keyedPool = keyedPool;
560             this.key = key;
561             this.minIdle = minIdle;
562         }
563 
564         /**
565          * {@inheritDoc}
566          */
567         @Override
568         public void run() {
569             boolean success = false;
570             try {
571                 if (keyedPool.getNumIdle(key) < minIdle) {
572                     keyedPool.addObject(key);
573                 }
574                 success = true;
575 
576             } catch (final Exception e) {
577                 cancel();
578 
579             } finally {
580                 // detect other types of Throwable and cancel this Timer
581                 if (!success) {
582                     cancel();
583                 }
584             }
585         }
586 
587         /**
588          * {@inheritDoc}
589          */
590         @Override
591         public String toString() {
592             final StringBuilder sb = new StringBuilder();
593             sb.append("KeyedObjectPoolMinIdleTimerTask");
594             sb.append("{minIdle=").append(minIdle);
595             sb.append(", key=").append(key);
596             sb.append(", keyedPool=").append(keyedPool);
597             sb.append('}');
598             return sb.toString();
599         }
600     }
601     /**
602      * Timer task that adds objects to the pool until the number of idle
603      * instances reaches the configured minIdle. Note that this is not the same
604      * as the pool's minIdle setting.
605      *
606      * @param <T> type of objects in the pool
607      */
608     private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask {
609 
610         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
611         private final int minIdle;
612 
613         /** Object pool */
614         private final ObjectPool<T> pool;
615 
616         /**
617          * Constructs a new ObjectPoolMinIdleTimerTask for the given pool with the
618          * given minIdle setting.
619          *
620          * @param pool
621          *            object pool
622          * @param minIdle
623          *            number of idle instances to maintain
624          * @throws IllegalArgumentException
625          *             if the pool is null
626          */
627         ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, final int minIdle)
628                 throws IllegalArgumentException {
629             if (pool == null) {
630                 throw new IllegalArgumentException(MSG_NULL_POOL);
631             }
632             this.pool = pool;
633             this.minIdle = minIdle;
634         }
635 
636         /**
637          * {@inheritDoc}
638          */
639         @Override
640         public void run() {
641             boolean success = false;
642             try {
643                 if (pool.getNumIdle() < minIdle) {
644                     pool.addObject();
645                 }
646                 success = true;
647 
648             } catch (final Exception e) {
649                 cancel();
650             } finally {
651                 // detect other types of Throwable and cancel this Timer
652                 if (!success) {
653                     cancel();
654                 }
655             }
656         }
657 
658         /**
659          * {@inheritDoc}
660          */
661         @Override
662         public String toString() {
663             final StringBuilder sb = new StringBuilder();
664             sb.append("ObjectPoolMinIdleTimerTask");
665             sb.append("{minIdle=").append(minIdle);
666             sb.append(", pool=").append(pool);
667             sb.append('}');
668             return sb.toString();
669         }
670     }
671 
672     /**
673      * A synchronized (thread-safe) KeyedObjectPool backed by the specified
674      * KeyedObjectPool.
675      * <p>
676      * <strong>Note:</strong> This should not be used on pool implementations that already
677      * provide proper synchronization such as the pools provided in the Commons
678      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
679      * objects to be returned before allowing another one to be borrowed with
680      * another layer of synchronization will cause liveliness issues or a
681      * deadlock.
682      * </p>
683      *
684      * @param <K> object pool key type
685      * @param <V> object pool value type
686      */
687     static final class SynchronizedKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
688 
689         /**
690          * Object whose monitor is used to synchronize methods on the wrapped
691          * pool.
692          */
693         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
694 
695         /** Underlying object pool */
696         private final KeyedObjectPool<K, V> keyedPool;
697 
698         /**
699          * Creates a new SynchronizedKeyedObjectPool wrapping the given pool
700          *
701          * @param keyedPool
702          *            KeyedObjectPool to wrap
703          * @throws IllegalArgumentException
704          *             if keyedPool is null
705          */
706         SynchronizedKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool)
707                 throws IllegalArgumentException {
708             if (keyedPool == null) {
709                 throw new IllegalArgumentException(
710                         MSG_NULL_KEYED_POOL);
711             }
712             this.keyedPool = keyedPool;
713         }
714 
715         /**
716          * {@inheritDoc}
717          */
718         @Override
719         public void addObject(final K key) throws Exception {
720             final WriteLock writeLock = readWriteLock.writeLock();
721             writeLock.lock();
722             try {
723                 keyedPool.addObject(key);
724             } finally {
725                 writeLock.unlock();
726             }
727         }
728 
729         /**
730          * {@inheritDoc}
731          */
732         @Override
733         public V borrowObject(final K key) throws Exception {
734             final WriteLock writeLock = readWriteLock.writeLock();
735             writeLock.lock();
736             try {
737                 return keyedPool.borrowObject(key);
738             } finally {
739                 writeLock.unlock();
740             }
741         }
742 
743         /**
744          * {@inheritDoc}
745          */
746         @Override
747         public void clear() throws Exception {
748             final WriteLock writeLock = readWriteLock.writeLock();
749             writeLock.lock();
750             try {
751                 keyedPool.clear();
752             } finally {
753                 writeLock.unlock();
754             }
755         }
756 
757         /**
758          * {@inheritDoc}
759          */
760         @Override
761         public void clear(final K key) throws Exception {
762             final WriteLock writeLock = readWriteLock.writeLock();
763             writeLock.lock();
764             try {
765                 keyedPool.clear(key);
766             } finally {
767                 writeLock.unlock();
768             }
769         }
770 
771         /**
772          * {@inheritDoc}
773          */
774         @Override
775         public void close() {
776             final WriteLock writeLock = readWriteLock.writeLock();
777             writeLock.lock();
778             try {
779                 keyedPool.close();
780             } catch (final Exception ignored) {
781                 // ignored as of Pool 2
782             } finally {
783                 writeLock.unlock();
784             }
785         }
786 
787         /**
788          * {@inheritDoc}
789          */
790         @Override
791         public List<K> getKeys() {
792             final ReadLock readLock = readWriteLock.readLock();
793             readLock.lock();
794             try {
795                 return keyedPool.getKeys();
796             } finally {
797                 readLock.unlock();
798             }
799         }
800 
801         /**
802          * {@inheritDoc}
803          */
804         @Override
805         public int getNumActive() {
806             final ReadLock readLock = readWriteLock.readLock();
807             readLock.lock();
808             try {
809                 return keyedPool.getNumActive();
810             } finally {
811                 readLock.unlock();
812             }
813         }
814 
815         /**
816          * {@inheritDoc}
817          */
818         @Override
819         public int getNumActive(final K key) {
820             final ReadLock readLock = readWriteLock.readLock();
821             readLock.lock();
822             try {
823                 return keyedPool.getNumActive(key);
824             } finally {
825                 readLock.unlock();
826             }
827         }
828 
829         /**
830          * {@inheritDoc}
831          */
832         @Override
833         public int getNumIdle() {
834             final ReadLock readLock = readWriteLock.readLock();
835             readLock.lock();
836             try {
837                 return keyedPool.getNumIdle();
838             } finally {
839                 readLock.unlock();
840             }
841         }
842 
843         /**
844          * {@inheritDoc}
845          */
846         @Override
847         public int getNumIdle(final K key) {
848             final ReadLock readLock = readWriteLock.readLock();
849             readLock.lock();
850             try {
851                 return keyedPool.getNumIdle(key);
852             } finally {
853                 readLock.unlock();
854             }
855         }
856 
857         /**
858          * {@inheritDoc}
859          */
860         @Override
861         public void invalidateObject(final K key, final V obj) {
862             final WriteLock writeLock = readWriteLock.writeLock();
863             writeLock.lock();
864             try {
865                 keyedPool.invalidateObject(key, obj);
866             } catch (final Exception ignored) {
867                 // ignored as of Pool 2
868             } finally {
869                 writeLock.unlock();
870             }
871         }
872 
873         /**
874          * {@inheritDoc}
875          */
876         @Override
877         public void returnObject(final K key, final V obj) {
878             final WriteLock writeLock = readWriteLock.writeLock();
879             writeLock.lock();
880             try {
881                 keyedPool.returnObject(key, obj);
882             } catch (final Exception ignored) {
883                 // ignored
884             } finally {
885                 writeLock.unlock();
886             }
887         }
888 
889         /**
890          * {@inheritDoc}
891          */
892         @Override
893         public String toString() {
894             final StringBuilder sb = new StringBuilder();
895             sb.append("SynchronizedKeyedObjectPool");
896             sb.append("{keyedPool=").append(keyedPool);
897             sb.append('}');
898             return sb.toString();
899         }
900     }
901 
902     /**
903      * A fully synchronized KeyedPooledObjectFactory that wraps a
904      * KeyedPooledObjectFactory and synchronizes access to the wrapped factory
905      * methods.
906      * <p>
907      * <strong>Note:</strong> This should not be used on pool implementations that already
908      * provide proper synchronization such as the pools provided in the Commons
909      * Pool library.
910      * </p>
911      *
912      * @param <K> pooled object factory key type
913      * @param <V> pooled object factory value type
914      */
915     private static final class SynchronizedKeyedPooledObjectFactory<K, V> implements KeyedPooledObjectFactory<K, V> {
916 
917         /** Synchronization lock */
918         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
919 
920         /** Wrapped factory */
921         private final KeyedPooledObjectFactory<K, V> keyedFactory;
922 
923         /**
924          * Creates a SynchronizedKeyedPooledObjectFactory wrapping the given
925          * factory.
926          *
927          * @param keyedFactory
928          *            underlying factory to wrap
929          * @throws IllegalArgumentException
930          *             if the factory is null
931          */
932         SynchronizedKeyedPooledObjectFactory(final KeyedPooledObjectFactory<K, V> keyedFactory) throws IllegalArgumentException {
933             if (keyedFactory == null) {
934                 throw new IllegalArgumentException(
935                         "keyedFactory must not be null.");
936             }
937             this.keyedFactory = keyedFactory;
938         }
939 
940         /**
941          * {@inheritDoc}
942          */
943         @Override
944         public void activateObject(final K key, final PooledObject<V> p) throws Exception {
945             writeLock.lock();
946             try {
947                 keyedFactory.activateObject(key, p);
948             } finally {
949                 writeLock.unlock();
950             }
951         }
952 
953         /**
954          * {@inheritDoc}
955          */
956         @Override
957         public void destroyObject(final K key, final PooledObject<V> p) throws Exception {
958             writeLock.lock();
959             try {
960                 keyedFactory.destroyObject(key, p);
961             } finally {
962                 writeLock.unlock();
963             }
964         }
965 
966         /**
967          * {@inheritDoc}
968          */
969         @Override
970         public PooledObject<V> makeObject(final K key) throws Exception {
971             writeLock.lock();
972             try {
973                 return keyedFactory.makeObject(key);
974             } finally {
975                 writeLock.unlock();
976             }
977         }
978 
979         /**
980          * {@inheritDoc}
981          */
982         @Override
983         public void passivateObject(final K key, final PooledObject<V> p) throws Exception {
984             writeLock.lock();
985             try {
986                 keyedFactory.passivateObject(key, p);
987             } finally {
988                 writeLock.unlock();
989             }
990         }
991 
992         /**
993          * {@inheritDoc}
994          */
995         @Override
996         public String toString() {
997             final StringBuilder sb = new StringBuilder();
998             sb.append("SynchronizedKeyedPooledObjectFactory");
999             sb.append("{keyedFactory=").append(keyedFactory);
1000             sb.append('}');
1001             return sb.toString();
1002         }
1003 
1004         /**
1005          * {@inheritDoc}
1006          */
1007         @Override
1008         public boolean validateObject(final K key, final PooledObject<V> p) {
1009             writeLock.lock();
1010             try {
1011                 return keyedFactory.validateObject(key, p);
1012             } finally {
1013                 writeLock.unlock();
1014             }
1015         }
1016     }
1017 
1018     /**
1019      * A synchronized (thread-safe) ObjectPool backed by the specified
1020      * ObjectPool.
1021      * <p>
1022      * <strong>Note:</strong> This should not be used on pool implementations that already
1023      * provide proper synchronization such as the pools provided in the Commons
1024      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1025      * objects to be returned before allowing another one to be borrowed with
1026      * another layer of synchronization will cause liveliness issues or a
1027      * deadlock.
1028      * </p>
1029      *
1030      * @param <T> type of objects in the pool
1031      */
1032     private static final class SynchronizedObjectPool<T> implements ObjectPool<T> {
1033 
1034         /**
1035          * Object whose monitor is used to synchronize methods on the wrapped
1036          * pool.
1037          */
1038         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
1039 
1040         /** The underlying object pool */
1041         private final ObjectPool<T> pool;
1042 
1043         /**
1044          * Creates a new SynchronizedObjectPool wrapping the given pool.
1045          *
1046          * @param pool
1047          *            the ObjectPool to be "wrapped" in a synchronized
1048          *            ObjectPool.
1049          * @throws IllegalArgumentException
1050          *             if the pool is null
1051          */
1052         SynchronizedObjectPool(final ObjectPool<T> pool)
1053                 throws IllegalArgumentException {
1054             if (pool == null) {
1055                 throw new IllegalArgumentException(MSG_NULL_POOL);
1056             }
1057             this.pool = pool;
1058         }
1059 
1060         /**
1061          * {@inheritDoc}
1062          */
1063         @Override
1064         public void addObject() throws Exception {
1065             final WriteLock writeLock = readWriteLock.writeLock();
1066             writeLock.lock();
1067             try {
1068                 pool.addObject();
1069             } finally {
1070                 writeLock.unlock();
1071             }
1072         }
1073 
1074         /**
1075          * {@inheritDoc}
1076          */
1077         @Override
1078         public T borrowObject() throws Exception {
1079             final WriteLock writeLock = readWriteLock.writeLock();
1080             writeLock.lock();
1081             try {
1082                 return pool.borrowObject();
1083             } finally {
1084                 writeLock.unlock();
1085             }
1086         }
1087 
1088         /**
1089          * {@inheritDoc}
1090          */
1091         @Override
1092         public void clear() throws Exception {
1093             final WriteLock writeLock = readWriteLock.writeLock();
1094             writeLock.lock();
1095             try {
1096                 pool.clear();
1097             } finally {
1098                 writeLock.unlock();
1099             }
1100         }
1101 
1102         /**
1103          * {@inheritDoc}
1104          */
1105         @Override
1106         public void close() {
1107             final WriteLock writeLock = readWriteLock.writeLock();
1108             writeLock.lock();
1109             try {
1110                 pool.close();
1111             } catch (final Exception ignored) {
1112                 // ignored as of Pool 2
1113             } finally {
1114                 writeLock.unlock();
1115             }
1116         }
1117 
1118         /**
1119          * {@inheritDoc}
1120          */
1121         @Override
1122         public int getNumActive() {
1123             final ReadLock readLock = readWriteLock.readLock();
1124             readLock.lock();
1125             try {
1126                 return pool.getNumActive();
1127             } finally {
1128                 readLock.unlock();
1129             }
1130         }
1131 
1132         /**
1133          * {@inheritDoc}
1134          */
1135         @Override
1136         public int getNumIdle() {
1137             final ReadLock readLock = readWriteLock.readLock();
1138             readLock.lock();
1139             try {
1140                 return pool.getNumIdle();
1141             } finally {
1142                 readLock.unlock();
1143             }
1144         }
1145 
1146         /**
1147          * {@inheritDoc}
1148          */
1149         @Override
1150         public void invalidateObject(final T obj) {
1151             final WriteLock writeLock = readWriteLock.writeLock();
1152             writeLock.lock();
1153             try {
1154                 pool.invalidateObject(obj);
1155             } catch (final Exception ignored) {
1156                 // ignored as of Pool 2
1157             } finally {
1158                 writeLock.unlock();
1159             }
1160         }
1161 
1162         /**
1163          * {@inheritDoc}
1164          */
1165         @Override
1166         public void returnObject(final T obj) {
1167             final WriteLock writeLock = readWriteLock.writeLock();
1168             writeLock.lock();
1169             try {
1170                 pool.returnObject(obj);
1171             } catch (final Exception ignored) {
1172                 // ignored as of Pool 2
1173             } finally {
1174                 writeLock.unlock();
1175             }
1176         }
1177 
1178         /**
1179          * {@inheritDoc}
1180          */
1181         @Override
1182         public String toString() {
1183             final StringBuilder sb = new StringBuilder();
1184             sb.append("SynchronizedObjectPool");
1185             sb.append("{pool=").append(pool);
1186             sb.append('}');
1187             return sb.toString();
1188         }
1189     }
1190 
1191     /**
1192      * A fully synchronized PooledObjectFactory that wraps a
1193      * PooledObjectFactory and synchronizes access to the wrapped factory
1194      * methods.
1195      * <p>
1196      * <strong>Note:</strong> This should not be used on pool implementations that already
1197      * provide proper synchronization such as the pools provided in the Commons
1198      * Pool library.
1199      * </p>
1200      *
1201      * @param <T> pooled object factory type
1202      */
1203     private static final class SynchronizedPooledObjectFactory<T> implements
1204             PooledObjectFactory<T> {
1205 
1206         /** Synchronization lock */
1207         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
1208 
1209         /** Wrapped factory */
1210         private final PooledObjectFactory<T> factory;
1211 
1212         /**
1213          * Creates a SynchronizedPoolableObjectFactory wrapping the given
1214          * factory.
1215          *
1216          * @param factory
1217          *            underlying factory to wrap
1218          * @throws IllegalArgumentException
1219          *             if the factory is null
1220          */
1221         SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory)
1222                 throws IllegalArgumentException {
1223             if (factory == null) {
1224                 throw new IllegalArgumentException("factory must not be null.");
1225             }
1226             this.factory = factory;
1227         }
1228 
1229         /**
1230          * {@inheritDoc}
1231          */
1232         @Override
1233         public void activateObject(final PooledObject<T> p) throws Exception {
1234             writeLock.lock();
1235             try {
1236                 factory.activateObject(p);
1237             } finally {
1238                 writeLock.unlock();
1239             }
1240         }
1241 
1242         /**
1243          * {@inheritDoc}
1244          */
1245         @Override
1246         public void destroyObject(final PooledObject<T> p) throws Exception {
1247             writeLock.lock();
1248             try {
1249                 factory.destroyObject(p);
1250             } finally {
1251                 writeLock.unlock();
1252             }
1253         }
1254 
1255         /**
1256          * {@inheritDoc}
1257          */
1258         @Override
1259         public PooledObject<T> makeObject() throws Exception {
1260             writeLock.lock();
1261             try {
1262                 return factory.makeObject();
1263             } finally {
1264                 writeLock.unlock();
1265             }
1266         }
1267 
1268         /**
1269          * {@inheritDoc}
1270          */
1271         @Override
1272         public void passivateObject(final PooledObject<T> p) throws Exception {
1273             writeLock.lock();
1274             try {
1275                 factory.passivateObject(p);
1276             } finally {
1277                 writeLock.unlock();
1278             }
1279         }
1280 
1281         /**
1282          * {@inheritDoc}
1283          */
1284         @Override
1285         public String toString() {
1286             final StringBuilder sb = new StringBuilder();
1287             sb.append("SynchronizedPoolableObjectFactory");
1288             sb.append("{factory=").append(factory);
1289             sb.append('}');
1290             return sb.toString();
1291         }
1292 
1293         /**
1294          * {@inheritDoc}
1295          */
1296         @Override
1297         public boolean validateObject(final PooledObject<T> p) {
1298             writeLock.lock();
1299             try {
1300                 return factory.validateObject(p);
1301             } finally {
1302                 writeLock.unlock();
1303             }
1304         }
1305     }
1306 
1307     /**
1308      * Timer used to periodically check pools idle object count. Because a
1309      * {@link Timer} creates a {@link Thread}, an IODH is used.
1310      */
1311     static class TimerHolder {
1312         static final Timer MIN_IDLE_TIMER = new Timer(true);
1313     }
1314 
1315     private static final String MSG_FACTOR_NEGATIVE = "factor must be positive.";
1316 
1317     private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";
1318 
1319     static final String MSG_NULL_KEY = "key must not be null.";
1320 
1321     private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
1322 
1323     static final String MSG_NULL_KEYS = "keys must not be null.";
1324 
1325     private static final String MSG_NULL_POOL = "pool must not be null.";
1326 
1327     /**
1328      * Periodically check the idle object count for each key in the
1329      * {@code Collection keys} in the keyedPool. At most one idle object will be
1330      * added per period.
1331      *
1332      * @param keyedPool
1333      *            the keyedPool to check periodically.
1334      * @param keys
1335      *            a collection of keys to check the idle object count.
1336      * @param minIdle
1337      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
1338      *            this then add an idle object.
1339      * @param periodMillis
1340      *            the frequency in milliseconds to check the number of idle objects in a
1341      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
1342      * @param <K> the type of the pool key
1343      * @param <V> the type of pool entries
1344      * @return a {@link Map} of key and {@link TimerTask} pairs that will
1345      *         periodically check the pools idle object count.
1346      * @throws IllegalArgumentException
1347      *             when {@code keyedPool}, {@code keys}, or any of the values in
1348      *             the collection is {@code null} or when {@code minIdle} is
1349      *             negative or when {@code period} isn't valid for
1350      *             {@link Timer#schedule(TimerTask, long, long)}.
1351      * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
1352      */
1353     public static <K, V> Map<K, TimerTask> checkMinIdle(
1354             final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys,
1355             final int minIdle, final long periodMillis)
1356             throws IllegalArgumentException {
1357         if (keys == null) {
1358             throw new IllegalArgumentException(MSG_NULL_KEYS);
1359         }
1360         final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
1361         keys.forEach(key -> tasks.put(key, checkMinIdle(keyedPool, key, minIdle, periodMillis)));
1362         return tasks;
1363     }
1364 
1365     /**
1366      * Periodically check the idle object count for the key in the keyedPool. At
1367      * most one idle object will be added per period. If there is an exception
1368      * when calling {@link KeyedObjectPool#addObject(Object)} then no more
1369      * checks for that key will be performed.
1370      *
1371      * @param keyedPool
1372      *            the keyedPool to check periodically.
1373      * @param key
1374      *            the key to check the idle count of.
1375      * @param minIdle
1376      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
1377      *            this then add an idle object.
1378      * @param periodMillis
1379      *            the frequency in milliseconds to check the number of idle objects in a
1380      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
1381      * @param <K> the type of the pool key
1382      * @param <V> the type of pool entries
1383      * @return the {@link TimerTask} that will periodically check the pools idle
1384      *         object count.
1385      * @throws IllegalArgumentException
1386      *             when {@code keyedPool}, {@code key} is {@code null} or
1387      *             when {@code minIdle} is negative or when {@code period} isn't
1388      *             valid for {@link Timer#schedule(TimerTask, long, long)}.
1389      */
1390     public static <K, V> TimerTask checkMinIdle(
1391             final KeyedObjectPool<K, V> keyedPool, final K key,
1392             final int minIdle, final long periodMillis)
1393             throws IllegalArgumentException {
1394         if (keyedPool == null) {
1395             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1396         }
1397         if (key == null) {
1398             throw new IllegalArgumentException(MSG_NULL_KEY);
1399         }
1400         if (minIdle < 0) {
1401             throw new IllegalArgumentException(MSG_MIN_IDLE);
1402         }
1403         final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
1404                 keyedPool, key, minIdle);
1405         getMinIdleTimer().schedule(task, 0L, periodMillis);
1406         return task;
1407     }
1408 
1409     /**
1410      * Periodically check the idle object count for the pool. At most one idle
1411      * object will be added per period. If there is an exception when calling
1412      * {@link ObjectPool#addObject()} then no more checks will be performed.
1413      *
1414      * @param pool
1415      *            the pool to check periodically.
1416      * @param minIdle
1417      *            if the {@link ObjectPool#getNumIdle()} is less than this then
1418      *            add an idle object.
1419      * @param periodMillis
1420      *            the frequency in milliseconds to check the number of idle objects in a pool,
1421      *            see {@link Timer#schedule(TimerTask, long, long)}.
1422      * @param <T> the type of objects in the pool
1423      * @return the {@link TimerTask} that will periodically check the pools idle
1424      *         object count.
1425      * @throws IllegalArgumentException
1426      *             when {@code pool} is {@code null} or when {@code minIdle} is
1427      *             negative or when {@code period} isn't valid for
1428      *             {@link Timer#schedule(TimerTask, long, long)}
1429      */
1430     public static <T> TimerTask checkMinIdle(final ObjectPool<T> pool,
1431             final int minIdle, final long periodMillis)
1432             throws IllegalArgumentException {
1433         if (pool == null) {
1434             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1435         }
1436         if (minIdle < 0) {
1437             throw new IllegalArgumentException(MSG_MIN_IDLE);
1438         }
1439         final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
1440         getMinIdleTimer().schedule(task, 0L, periodMillis);
1441         return task;
1442     }
1443 
1444     /**
1445      * Should the supplied Throwable be re-thrown (eg if it is an instance of
1446      * one of the Throwables that should never be swallowed). Used by the pool
1447      * error handling for operations that throw exceptions that normally need to
1448      * be ignored.
1449      *
1450      * @param t
1451      *            The Throwable to check
1452      * @throws ThreadDeath
1453      *             if that is passed in
1454      * @throws VirtualMachineError
1455      *             if that is passed in
1456      */
1457     public static void checkRethrow(final Throwable t) {
1458         if (t instanceof ThreadDeath) {
1459             throw (ThreadDeath) t;
1460         }
1461         if (t instanceof VirtualMachineError) {
1462             throw (VirtualMachineError) t;
1463         }
1464         // All other instances of Throwable will be silently swallowed
1465     }
1466 
1467     /**
1468      * Returns a pool that adaptively decreases its size when idle objects are
1469      * no longer needed. This is intended as an always thread-safe alternative
1470      * to using an idle object evictor provided by many pool implementations.
1471      * This is also an effective way to shrink FIFO ordered pools that
1472      * experience load spikes.
1473      *
1474      * @param keyedPool
1475      *            the KeyedObjectPool to be decorated so it shrinks its idle
1476      *            count when possible.
1477      * @param <K> the type of the pool key
1478      * @param <V> the type of pool entries
1479      * @throws IllegalArgumentException
1480      *             when {@code keyedPool} is {@code null}.
1481      * @return a pool that adaptively decreases its size when idle objects are
1482      *         no longer needed.
1483      * @see #erodingPool(KeyedObjectPool, float)
1484      * @see #erodingPool(KeyedObjectPool, float, boolean)
1485      */
1486     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool) {
1487         return erodingPool(keyedPool, 1f);
1488     }
1489 
1490     /**
1491      * Returns a pool that adaptively decreases its size when idle objects are
1492      * no longer needed. This is intended as an always thread-safe alternative
1493      * to using an idle object evictor provided by many pool implementations.
1494      * This is also an effective way to shrink FIFO ordered pools that
1495      * experience load spikes.
1496      * <p>
1497      * The factor parameter provides a mechanism to tweak the rate at which the
1498      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1499      * try to shrink its size more often. Values greater than 1 cause the pool
1500      * to less frequently try to shrink its size.
1501      * </p>
1502      *
1503      * @param keyedPool
1504      *            the KeyedObjectPool to be decorated so it shrinks its idle
1505      *            count when possible.
1506      * @param factor
1507      *            a positive value to scale the rate at which the pool tries to
1508      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1509      *            shrinks more aggressively. If 1 &lt; factor then the pool
1510      *            shrinks less aggressively.
1511      * @param <K> the type of the pool key
1512      * @param <V> the type of pool entries
1513      * @throws IllegalArgumentException
1514      *             when {@code keyedPool} is {@code null} or when {@code factor}
1515      *             is not positive.
1516      * @return a pool that adaptively decreases its size when idle objects are
1517      *         no longer needed.
1518      * @see #erodingPool(KeyedObjectPool, float, boolean)
1519      */
1520     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
1521         return erodingPool(keyedPool, factor, false);
1522     }
1523 
1524     /**
1525      * Returns a pool that adaptively decreases its size when idle objects are
1526      * no longer needed. This is intended as an always thread-safe alternative
1527      * to using an idle object evictor provided by many pool implementations.
1528      * This is also an effective way to shrink FIFO ordered pools that
1529      * experience load spikes.
1530      * <p>
1531      * The factor parameter provides a mechanism to tweak the rate at which the
1532      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1533      * try to shrink its size more often. Values greater than 1 cause the pool
1534      * to less frequently try to shrink its size.
1535      * </p>
1536      * <p>
1537      * The perKey parameter determines if the pool shrinks on a whole pool basis
1538      * or a per key basis. When perKey is false, the keys do not have an effect
1539      * on the rate at which the pool tries to shrink its size. When perKey is
1540      * true, each key is shrunk independently.
1541      * </p>
1542      *
1543      * @param keyedPool
1544      *            the KeyedObjectPool to be decorated so it shrinks its idle
1545      *            count when possible.
1546      * @param factor
1547      *            a positive value to scale the rate at which the pool tries to
1548      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1549      *            shrinks more aggressively. If 1 &lt; factor then the pool
1550      *            shrinks less aggressively.
1551      * @param perKey
1552      *            when true, each key is treated independently.
1553      * @param <K> the type of the pool key
1554      * @param <V> the type of pool entries
1555      * @throws IllegalArgumentException
1556      *             when {@code keyedPool} is {@code null} or when {@code factor}
1557      *             is not positive.
1558      * @return a pool that adaptively decreases its size when idle objects are
1559      *         no longer needed.
1560      * @see #erodingPool(KeyedObjectPool)
1561      * @see #erodingPool(KeyedObjectPool, float)
1562      */
1563     public static <K, V> KeyedObjectPool<K, V> erodingPool(
1564             final KeyedObjectPool<K, V> keyedPool, final float factor,
1565             final boolean perKey) {
1566         if (keyedPool == null) {
1567             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1568         }
1569         if (factor <= 0f) {
1570             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
1571         }
1572         if (perKey) {
1573             return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
1574         }
1575         return new ErodingKeyedObjectPool<>(keyedPool, factor);
1576     }
1577 
1578     /**
1579      * Returns a pool that adaptively decreases its size when idle objects are
1580      * no longer needed. This is intended as an always thread-safe alternative
1581      * to using an idle object evictor provided by many pool implementations.
1582      * This is also an effective way to shrink FIFO ordered pools that
1583      * experience load spikes.
1584      *
1585      * @param pool
1586      *            the ObjectPool to be decorated so it shrinks its idle count
1587      *            when possible.
1588      * @param <T> the type of objects in the pool
1589      * @throws IllegalArgumentException
1590      *             when {@code pool} is {@code null}.
1591      * @return a pool that adaptively decreases its size when idle objects are
1592      *         no longer needed.
1593      * @see #erodingPool(ObjectPool, float)
1594      */
1595     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool) {
1596         return erodingPool(pool, 1f);
1597     }
1598 
1599     /**
1600      * Returns a pool that adaptively decreases its size when idle objects are
1601      * no longer needed. This is intended as an always thread-safe alternative
1602      * to using an idle object evictor provided by many pool implementations.
1603      * This is also an effective way to shrink FIFO ordered pools that
1604      * experience load spikes.
1605      * <p>
1606      * The factor parameter provides a mechanism to tweak the rate at which the
1607      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1608      * try to shrink its size more often. Values greater than 1 cause the pool
1609      * to less frequently try to shrink its size.
1610      * </p>
1611      *
1612      * @param pool
1613      *            the ObjectPool to be decorated so it shrinks its idle count
1614      *            when possible.
1615      * @param factor
1616      *            a positive value to scale the rate at which the pool tries to
1617      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1618      *            shrinks more aggressively. If 1 &lt; factor then the pool
1619      *            shrinks less aggressively.
1620      * @param <T> the type of objects in the pool
1621      * @throws IllegalArgumentException
1622      *             when {@code pool} is {@code null} or when {@code factor} is
1623      *             not positive.
1624      * @return a pool that adaptively decreases its size when idle objects are
1625      *         no longer needed.
1626      * @see #erodingPool(ObjectPool)
1627      */
1628     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool, final float factor) {
1629         if (pool == null) {
1630             throw new IllegalArgumentException(MSG_NULL_POOL);
1631         }
1632         if (factor <= 0f) {
1633             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
1634         }
1635         return new ErodingObjectPool<>(pool, factor);
1636     }
1637 
1638     /**
1639      * Gets the {@code Timer} for checking keyedPool's idle count.
1640      *
1641      * @return the {@link Timer} for checking keyedPool's idle count.
1642      */
1643     private static Timer getMinIdleTimer() {
1644         return TimerHolder.MIN_IDLE_TIMER;
1645     }
1646 
1647     /**
1648      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
1649      * each key in {@code keys} for {@code count} number of times. This has
1650      * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)}
1651      * for each key in the {@code keys} collection.
1652      *
1653      * @param keyedPool
1654      *            the keyedPool to prefill.
1655      * @param keys
1656      *            {@link Collection} of keys to add objects for.
1657      * @param count
1658      *            the number of idle objects to add for each {@code key}.
1659      * @param <K> the type of the pool key
1660      * @param <V> the type of pool entries
1661      * @throws Exception
1662      *             when {@link KeyedObjectPool#addObject(Object)} fails.
1663      * @throws IllegalArgumentException
1664      *             when {@code keyedPool}, {@code keys}, or any value in
1665      *             {@code keys} is {@code null}.
1666      * @see #prefill(KeyedObjectPool, Object, int)
1667      * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}.
1668      */
1669     @Deprecated
1670     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
1671             final Collection<K> keys, final int count) throws Exception,
1672             IllegalArgumentException {
1673         if (keys == null) {
1674             throw new IllegalArgumentException(MSG_NULL_KEYS);
1675         }
1676         keyedPool.addObjects(keys, count);
1677     }
1678 
1679     /**
1680      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
1681      * {@code key} {@code count} number of times.
1682      *
1683      * @param keyedPool
1684      *            the keyedPool to prefill.
1685      * @param key
1686      *            the key to add objects for.
1687      * @param count
1688      *            the number of idle objects to add for {@code key}.
1689      * @param <K> the type of the pool key
1690      * @param <V> the type of pool entries
1691      * @throws Exception
1692      *             when {@link KeyedObjectPool#addObject(Object)} fails.
1693      * @throws IllegalArgumentException
1694      *             when {@code keyedPool} or {@code key} is {@code null}.
1695      * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}.
1696      */
1697     @Deprecated
1698     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
1699             final K key, final int count) throws Exception,
1700             IllegalArgumentException {
1701         if (keyedPool == null) {
1702             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1703         }
1704         keyedPool.addObjects(key, count);
1705     }
1706 
1707     /**
1708      * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number
1709      * of times.
1710      *
1711      * @param pool
1712      *            the pool to prefill.
1713      * @param count
1714      *            the number of idle objects to add.
1715      * @param <T> the type of objects in the pool
1716      * @throws Exception
1717      *             when {@link ObjectPool#addObject()} fails.
1718      * @throws IllegalArgumentException
1719      *             when {@code pool} is {@code null}.
1720      * @deprecated Use {@link ObjectPool#addObjects(int)}.
1721      */
1722     @Deprecated
1723     public static <T> void prefill(final ObjectPool<T> pool, final int count)
1724             throws Exception {
1725         if (pool == null) {
1726             throw new IllegalArgumentException(MSG_NULL_POOL);
1727         }
1728         pool.addObjects(count);
1729     }
1730 
1731     /**
1732      * Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
1733      * the specified KeyedPooledObjectFactory.
1734      *
1735      * @param keyedFactory
1736      *            the KeyedPooledObjectFactory to be "wrapped" in a
1737      *            synchronized KeyedPooledObjectFactory.
1738      * @param <K> the type of the pool key
1739      * @param <V> the type of pool entries
1740      * @return a synchronized view of the specified KeyedPooledObjectFactory.
1741      */
1742     public static <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory(
1743         final KeyedPooledObjectFactory<K, V> keyedFactory) {
1744         return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
1745     }
1746 
1747     /**
1748      * Returns a synchronized (thread-safe) KeyedObjectPool backed by the
1749      * specified KeyedObjectPool.
1750      * <p>
1751      * <strong>Note:</strong> This should not be used on pool implementations that already
1752      * provide proper synchronization such as the pools provided in the Commons
1753      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1754      * objects to be returned before allowing another one to be borrowed with
1755      * another layer of synchronization will cause liveliness issues or a
1756      * deadlock.
1757      * </p>
1758      *
1759      * @param keyedPool
1760      *            the KeyedObjectPool to be "wrapped" in a synchronized
1761      *            KeyedObjectPool.
1762      * @param <K> the type of the pool key
1763      * @param <V> the type of pool entries
1764      * @return a synchronized view of the specified KeyedObjectPool.
1765      */
1766     public static <K, V> KeyedObjectPool<K, V> synchronizedPool(final KeyedObjectPool<K, V> keyedPool) {
1767         /*
1768          * assert !(keyedPool instanceof GenericKeyedObjectPool) :
1769          * "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool
1770          * instanceof StackKeyedObjectPool) :
1771          * "StackKeyedObjectPool is already thread-safe"; assert
1772          * !"org.apache.commons.pool.composite.CompositeKeyedObjectPool"
1773          * .equals(keyedPool.getClass().getName()) :
1774          * "CompositeKeyedObjectPools are already thread-safe";
1775          */
1776         return new SynchronizedKeyedObjectPool<>(keyedPool);
1777     }
1778 
1779     /**
1780      * Returns a synchronized (thread-safe) ObjectPool backed by the specified
1781      * ObjectPool.
1782      * <p>
1783      * <strong>Note:</strong> This should not be used on pool implementations that already
1784      * provide proper synchronization such as the pools provided in the Commons
1785      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1786      * objects to be returned before allowing another one to be borrowed with
1787      * another layer of synchronization will cause liveliness issues or a
1788      * deadlock.
1789      * </p>
1790      *
1791      * @param <T> the type of objects in the pool
1792      * @param pool
1793      *            the ObjectPool to be "wrapped" in a synchronized ObjectPool.
1794      * @throws IllegalArgumentException
1795      *             when {@code pool} is {@code null}.
1796      * @return a synchronized view of the specified ObjectPool.
1797      */
1798     public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) {
1799         if (pool == null) {
1800             throw new IllegalArgumentException(MSG_NULL_POOL);
1801         }
1802 
1803         /*
1804          * assert !(pool instanceof GenericObjectPool) :
1805          * "GenericObjectPool is already thread-safe"; assert !(pool instanceof
1806          * SoftReferenceObjectPool) :
1807          * "SoftReferenceObjectPool is already thread-safe"; assert !(pool
1808          * instanceof StackObjectPool) :
1809          * "StackObjectPool is already thread-safe"; assert
1810          * !"org.apache.commons.pool.composite.CompositeObjectPool"
1811          * .equals(pool.getClass().getName()) :
1812          * "CompositeObjectPools are already thread-safe";
1813          */
1814         return new SynchronizedObjectPool<>(pool);
1815     }
1816 
1817     /**
1818      * Returns a synchronized (thread-safe) PooledObjectFactory backed by the
1819      * specified PooledObjectFactory.
1820      *
1821      * @param factory
1822      *            the PooledObjectFactory to be "wrapped" in a synchronized
1823      *            PooledObjectFactory.
1824      * @param <T> the type of objects in the pool
1825      * @return a synchronized view of the specified PooledObjectFactory.
1826      */
1827     public static <T> PooledObjectFactory<T> synchronizedPooledFactory(final PooledObjectFactory<T> factory) {
1828         return new SynchronizedPooledObjectFactory<>(factory);
1829     }
1830 
1831     /**
1832      * PoolUtils instances should NOT be constructed in standard programming.
1833      * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
1834      * This constructor is public to permit tools that require a JavaBean
1835      * instance to operate.
1836      */
1837     public PoolUtils() {
1838     }
1839 }