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