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.tomcat.dbcp.pool2.impl;
18
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24 import java.util.Set;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.atomic.AtomicLong;
28
29 import org.apache.tomcat.dbcp.pool2.ObjectPool;
30 import org.apache.tomcat.dbcp.pool2.PoolUtils;
31 import org.apache.tomcat.dbcp.pool2.PooledObject;
32 import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
33 import org.apache.tomcat.dbcp.pool2.PooledObjectState;
34 import org.apache.tomcat.dbcp.pool2.UsageTracking;
35
36 /**
37  * A configurable {@link ObjectPool} implementation.
38  * <p>
39  * When coupled with the appropriate {@link PooledObjectFactory},
40  * <code>GenericObjectPool</code> provides robust pooling functionality for
41  * arbitrary objects.
42  * </p>
43  * <p>
44  * Optionally, one may configure the pool to examine and possibly evict objects
45  * as they sit idle in the pool and to ensure that a minimum number of idle
46  * objects are available. This is performed by an "idle object eviction" thread,
47  * which runs asynchronously. Caution should be used when configuring this
48  * optional feature. Eviction runs contend with client threads for access to
49  * objects in the pool, so if they run too frequently performance issues may
50  * result.
51  * </p>
52  * <p>
53  * The pool can also be configured to detect and remove "abandoned" objects,
54  * i.e. objects that have been checked out of the pool but neither used nor
55  * returned before the configured
56  * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}.
57  * Abandoned object removal can be configured to happen when
58  * <code>borrowObject</code> is invoked and the pool is close to starvation, or
59  * it can be executed by the idle object evictor, or both. If pooled objects
60  * implement the {@link org.apache.tomcat.dbcp.pool2.TrackedUse} interface,
61  * their last use will be queried
62  * using the <code>getLastUsed</code> method on that interface; otherwise
63  * abandonment is determined by how long an object has been checked out from
64  * the pool.
65  * </p>
66  * <p>
67  * Implementation note: To prevent possible deadlocks, care has been taken to
68  * ensure that no call to a factory method will occur within a synchronization
69  * block. See POOL-125 and DBCP-44 for more information.
70  * </p>
71  * <p>
72  * This class is intended to be thread-safe.
73  * </p>
74  *
75  * @see GenericKeyedObjectPool
76  *
77  * @param <T> Type of element pooled in this pool.
78  *
79  * @since 2.0
80  */

81 public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
82         implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {
83
84     /**
85      * Creates a new <code>GenericObjectPool</code> using defaults from
86      * {@link GenericObjectPoolConfig}.
87      *
88      * @param factory The object factory to be used to create object instances
89      *                used by this pool
90      */

91     public GenericObjectPool(final PooledObjectFactory<T> factory) {
92         this(factory, new GenericObjectPoolConfig<T>());
93     }
94
95     /**
96      * Creates a new <code>GenericObjectPool</code> using a specific
97      * configuration.
98      *
99      * @param factory   The object factory to be used to create object instances
100      *                  used by this pool
101      * @param config    The configuration to use for this pool instance. The
102      *                  configuration is used by value. Subsequent changes to
103      *                  the configuration object will not be reflected in the
104      *                  pool.
105      */

106     public GenericObjectPool(final PooledObjectFactory<T> factory,
107             final GenericObjectPoolConfig<T> config) {
108
109         super(config, ONAME_BASE, config.getJmxNamePrefix());
110
111         if (factory == null) {
112             jmxUnregister(); // tidy up
113             throw new IllegalArgumentException("factory may not be null");
114         }
115         this.factory = factory;
116
117         idleObjects = new LinkedBlockingDeque<>(config.getFairness());
118
119         setConfig(config);
120     }
121
122     /**
123      * Creates a new <code>GenericObjectPool</code> that tracks and destroys
124      * objects that are checked out, but never returned to the pool.
125      *
126      * @param factory   The object factory to be used to create object instances
127      *                  used by this pool
128      * @param config    The base pool configuration to use for this pool instance.
129      *                  The configuration is used by value. Subsequent changes to
130      *                  the configuration object will not be reflected in the
131      *                  pool.
132      * @param abandonedConfig  Configuration for abandoned object identification
133      *                         and removal.  The configuration is used by value.
134      */

135     public GenericObjectPool(final PooledObjectFactory<T> factory,
136             final GenericObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
137         this(factory, config);
138         setAbandonedConfig(abandonedConfig);
139     }
140
141     /**
142      * Returns the cap on the number of "idle" instances in the pool. If maxIdle
143      * is set too low on heavily loaded systems it is possible you will see
144      * objects being destroyed and almost immediately new objects being created.
145      * This is a result of the active threads momentarily returning objects
146      * faster than they are requesting them, causing the number of idle
147      * objects to rise above maxIdle. The best value for maxIdle for heavily
148      * loaded system will vary but the default is a good starting point.
149      *
150      * @return the maximum number of "idle" instances that can be held in the
151      *         pool or a negative value if there is no limit
152      *
153      * @see #setMaxIdle
154      */

155     @Override
156     public int getMaxIdle() {
157         return maxIdle;
158     }
159
160     /**
161      * Returns the cap on the number of "idle" instances in the pool. If maxIdle
162      * is set too low on heavily loaded systems it is possible you will see
163      * objects being destroyed and almost immediately new objects being created.
164      * This is a result of the active threads momentarily returning objects
165      * faster than they are requesting them, causing the number of idle
166      * objects to rise above maxIdle. The best value for maxIdle for heavily
167      * loaded system will vary but the default is a good starting point.
168      *
169      * @param maxIdle
170      *            The cap on the number of "idle" instances in the pool. Use a
171      *            negative value to indicate an unlimited number of idle
172      *            instances
173      *
174      * @see #getMaxIdle
175      */

176     public void setMaxIdle(final int maxIdle) {
177         this.maxIdle = maxIdle;
178     }
179
180     /**
181      * Sets the target for the minimum number of idle objects to maintain in
182      * the pool. This setting only has an effect if it is positive and
183      * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
184      * is the case, an attempt is made to ensure that the pool has the required
185      * minimum number of instances during idle object eviction runs.
186      * <p>
187      * If the configured value of minIdle is greater than the configured value
188      * for maxIdle then the value of maxIdle will be used instead.
189      * </p>
190      *
191      * @param minIdle
192      *            The minimum number of objects.
193      *
194      * @see #getMinIdle()
195      * @see #getMaxIdle()
196      * @see #getTimeBetweenEvictionRunsMillis()
197      */

198     public void setMinIdle(final int minIdle) {
199         this.minIdle = minIdle;
200     }
201
202     /**
203      * Returns the target for the minimum number of idle objects to maintain in
204      * the pool. This setting only has an effect if it is positive and
205      * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
206      * is the case, an attempt is made to ensure that the pool has the required
207      * minimum number of instances during idle object eviction runs.
208      * <p>
209      * If the configured value of minIdle is greater than the configured value
210      * for maxIdle then the value of maxIdle will be used instead.
211      * </p>
212      *
213      * @return The minimum number of objects.
214      *
215      * @see #setMinIdle(int)
216      * @see #setMaxIdle(int)
217      * @see #setTimeBetweenEvictionRunsMillis(long)
218      */

219     @Override
220     public int getMinIdle() {
221         final int maxIdleSave = getMaxIdle();
222         if (this.minIdle > maxIdleSave) {
223             return maxIdleSave;
224         }
225         return minIdle;
226     }
227
228     /**
229      * Gets whether or not abandoned object removal is configured for this pool.
230      *
231      * @return true if this pool is configured to detect and remove
232      * abandoned objects
233      */

234     @Override
235     public boolean isAbandonedConfig() {
236         return abandonedConfig != null;
237     }
238
239     /**
240      * Gets whether this pool identifies and logs any abandoned objects.
241      *
242      * @return {@code trueif abandoned object removal is configured for this
243      *         pool and removal events are to be logged otherwise {@code false}
244      *
245      * @see AbandonedConfig#getLogAbandoned()
246      */

247     @Override
248     public boolean getLogAbandoned() {
249         final AbandonedConfig ac = this.abandonedConfig;
250         return ac != null && ac.getLogAbandoned();
251     }
252
253     /**
254      * Gets whether a check is made for abandoned objects when an object is borrowed
255      * from this pool.
256      *
257      * @return {@code trueif abandoned object removal is configured to be
258      *         activated by borrowObject otherwise {@code false}
259      *
260      * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
261      */

262     @Override
263     public boolean getRemoveAbandonedOnBorrow() {
264         final AbandonedConfig ac = this.abandonedConfig;
265         return ac != null && ac.getRemoveAbandonedOnBorrow();
266     }
267
268     /**
269      * Gets whether a check is made for abandoned objects when the evictor runs.
270      *
271      * @return {@code trueif abandoned object removal is configured to be
272      *         activated when the evictor runs otherwise {@code false}
273      *
274      * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
275      */

276     @Override
277     public boolean getRemoveAbandonedOnMaintenance() {
278         final AbandonedConfig ac = this.abandonedConfig;
279         return ac != null && ac.getRemoveAbandonedOnMaintenance();
280     }
281
282     /**
283      * Obtains the timeout before which an object will be considered to be
284      * abandoned by this pool.
285      *
286      * @return The abandoned object timeout in seconds if abandoned object
287      *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
288      *
289      * @see AbandonedConfig#getRemoveAbandonedTimeout()
290      */

291     @Override
292     public int getRemoveAbandonedTimeout() {
293         final AbandonedConfig ac = this.abandonedConfig;
294         return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
295     }
296
297
298     /**
299      * Sets the base pool configuration.
300      *
301      * @param conf the new configuration to use. This is used by value.
302      *
303      * @see GenericObjectPoolConfig
304      */

305     public void setConfig(final GenericObjectPoolConfig<T> conf) {
306         super.setConfig(conf);
307         setMaxIdle(conf.getMaxIdle());
308         setMinIdle(conf.getMinIdle());
309         setMaxTotal(conf.getMaxTotal());
310     }
311
312     /**
313      * Sets the abandoned object removal configuration.
314      *
315      * @param abandonedConfig the new configuration to use. This is used by value.
316      *
317      * @see AbandonedConfig
318      */

319     public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
320         if (abandonedConfig == null) {
321             this.abandonedConfig = null;
322         } else {
323             this.abandonedConfig = new AbandonedConfig();
324             this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
325             this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
326             this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
327             this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance());
328             this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
329             this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
330             this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace());
331         }
332     }
333
334     /**
335      * Obtains a reference to the factory used to create, destroy and validate
336      * the objects used by this pool.
337      *
338      * @return the factory
339      */

340     public PooledObjectFactory<T> getFactory() {
341         return factory;
342     }
343
344     /**
345      * Equivalent to <code>{@link #borrowObject(long)
346      * borrowObject}({@link #getMaxWaitMillis()})</code>.
347      * <p>
348      * {@inheritDoc}
349      * </p>
350      */

351     @Override
352     public T borrowObject() throws Exception {
353         return borrowObject(getMaxWaitMillis());
354     }
355
356     /**
357      * Borrows an object from the pool using the specific waiting time which only
358      * applies if {@link #getBlockWhenExhausted()} is true.
359      * <p>
360      * If there is one or more idle instance available in the pool, then an
361      * idle instance will be selected based on the value of {@link #getLifo()},
362      * activated and returned. If activation fails, or {@link #getTestOnBorrow()
363      * testOnBorrow} is set to <code>true</code> and validation fails, the
364      * instance is destroyed and the next available instance is examined. This
365      * continues until either a valid instance is returned or there are no more
366      * idle instances available.
367      * </p>
368      * <p>
369      * If there are no idle instances available in the pool, behavior depends on
370      * the {@link #getMaxTotal() maxTotal}, (if applicable)
371      * {@link #getBlockWhenExhausted()} and the value passed in to the
372      * <code>borrowMaxWaitMillis</code> parameter. If the number of instances
373      * checked out from the pool is less than <code>maxTotal,</code> a new
374      * instance is created, activated and (if applicable) validated and returned
375      * to the caller. If validation fails, a <code>NoSuchElementException</code>
376      * is thrown.
377      * </p>
378      * <p>
379      * If the pool is exhausted (no available idle instances and no capacity to
380      * create new ones), this method will either block (if
381      * {@link #getBlockWhenExhausted()} is true) or throw a
382      * <code>NoSuchElementException</code> (if
383      * {@link #getBlockWhenExhausted()} is false). The length of time that this
384      * method will block when {@link #getBlockWhenExhausted()} is true is
385      * determined by the value passed in to the <code>borrowMaxWaitMillis</code>
386      * parameter.
387      * </p>
388      * <p>
389      * When the pool is exhausted, multiple calling threads may be
390      * simultaneously blocked waiting for instances to become available. A
391      * "fairness" algorithm has been implemented to ensure that threads receive
392      * available instances in request arrival order.
393      * </p>
394      *
395      * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
396      *                            to become available
397      *
398      * @return object instance from the pool
399      *
400      * @throws NoSuchElementException if an instance cannot be returned
401      *
402      * @throws Exception if an object instance cannot be returned due to an
403      *                   error
404      */

405     public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
406         assertOpen();
407
408         final AbandonedConfig ac = this.abandonedConfig;
409         if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
410                 (getNumIdle() < 2) &&
411                 (getNumActive() > getMaxTotal() - 3) ) {
412             removeAbandoned(ac);
413         }
414
415         PooledObject<T> p = null;
416
417         // Get local copy of current config so it is consistent for entire
418         // method execution
419         final boolean blockWhenExhausted = getBlockWhenExhausted();
420
421         boolean create;
422         final long waitTime = System.currentTimeMillis();
423
424         while (p == null) {
425             create = false;
426             p = idleObjects.pollFirst();
427             if (p == null) {
428                 p = create();
429                 if (p != null) {
430                     create = true;
431                 }
432             }
433             if (blockWhenExhausted) {
434                 if (p == null) {
435                     if (borrowMaxWaitMillis < 0) {
436                         p = idleObjects.takeFirst();
437                     } else {
438                         p = idleObjects.pollFirst(borrowMaxWaitMillis,
439                                 TimeUnit.MILLISECONDS);
440                     }
441                 }
442                 if (p == null) {
443                     throw new NoSuchElementException(
444                             "Timeout waiting for idle object");
445                 }
446             } else {
447                 if (p == null) {
448                     throw new NoSuchElementException("Pool exhausted");
449                 }
450             }
451             if (!p.allocate()) {
452                 p = null;
453             }
454
455             if (p != null) {
456                 try {
457                     factory.activateObject(p);
458                 } catch (final Exception e) {
459                     try {
460                         destroy(p);
461                     } catch (final Exception e1) {
462                         // Ignore - activation failure is more important
463                     }
464                     p = null;
465                     if (create) {
466                         final NoSuchElementException nsee = new NoSuchElementException(
467                                 "Unable to activate object");
468                         nsee.initCause(e);
469                         throw nsee;
470                     }
471                 }
472                 if (p != null && getTestOnBorrow()) {
473                     boolean validate = false;
474                     Throwable validationThrowable = null;
475                     try {
476                         validate = factory.validateObject(p);
477                     } catch (final Throwable t) {
478                         PoolUtils.checkRethrow(t);
479                         validationThrowable = t;
480                     }
481                     if (!validate) {
482                         try {
483                             destroy(p);
484                             destroyedByBorrowValidationCount.incrementAndGet();
485                         } catch (final Exception e) {
486                             // Ignore - validation failure is more important
487                         }
488                         p = null;
489                         if (create) {
490                             final NoSuchElementException nsee = new NoSuchElementException(
491                                     "Unable to validate object");
492                             nsee.initCause(validationThrowable);
493                             throw nsee;
494                         }
495                     }
496                 }
497             }
498         }
499
500         updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
501
502         return p.getObject();
503     }
504
505     /**
506      * {@inheritDoc}
507      * <p>
508      * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
509      * number of idle instances has reached this value, the returning instance
510      * is destroyed.
511      * </p>
512      * <p>
513      * If {@link #getTestOnReturn() testOnReturn} == true, the returning
514      * instance is validated before being returned to the idle instance pool. In
515      * this caseif validation fails, the instance is destroyed.
516      * </p>
517      * <p>
518      * Exceptions encountered destroying objects for any reason are swallowed
519      * but notified via a
520      * {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.
521      * </p>
522      */

523     @Override
524     public void returnObject(final T obj) {
525         final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
526
527         if (p == null) {
528             if (!isAbandonedConfig()) {
529                 throw new IllegalStateException(
530                         "Returned object not currently part of this pool");
531             }
532             return// Object was abandoned and removed
533         }
534
535         markReturningState(p);
536
537         final long activeTime = p.getActiveTimeMillis();
538
539         if (getTestOnReturn() && !factory.validateObject(p)) {
540             try {
541                 destroy(p);
542             } catch (final Exception e) {
543                 swallowException(e);
544             }
545             try {
546                 ensureIdle(1, false);
547             } catch (final Exception e) {
548                 swallowException(e);
549             }
550             updateStatsReturn(activeTime);
551             return;
552         }
553
554         try {
555             factory.passivateObject(p);
556         } catch (final Exception e1) {
557             swallowException(e1);
558             try {
559                 destroy(p);
560             } catch (final Exception e) {
561                 swallowException(e);
562             }
563             try {
564                 ensureIdle(1, false);
565             } catch (final Exception e) {
566                 swallowException(e);
567             }
568             updateStatsReturn(activeTime);
569             return;
570         }
571
572         if (!p.deallocate()) {
573             throw new IllegalStateException(
574                     "Object has already been returned to this pool or is invalid");
575         }
576
577         final int maxIdleSave = getMaxIdle();
578         if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
579             try {
580                 destroy(p);
581             } catch (final Exception e) {
582                 swallowException(e);
583             }
584             try {
585                 ensureIdle(1, false);
586             } catch (final Exception e) {
587                 swallowException(e);
588             }
589         } else {
590             if (getLifo()) {
591                 idleObjects.addFirst(p);
592             } else {
593                 idleObjects.addLast(p);
594             }
595             if (isClosed()) {
596                 // Pool closed while object was being added to idle objects.
597                 // Make sure the returned object is destroyed rather than left
598                 // in the idle object pool (which would effectively be a leak)
599                 clear();
600             }
601         }
602         updateStatsReturn(activeTime);
603     }
604
605     /**
606      * {@inheritDoc}
607      * <p>
608      * Activation of this method decrements the active count and attempts to
609      * destroy the instance.
610      * </p>
611      *
612      * @throws Exception             if an exception occurs destroying the
613      *                               object
614      * @throws IllegalStateException if obj does not belong to this pool
615      */

616     @Override
617     public void invalidateObject(final T obj) throws Exception {
618         final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
619         if (p == null) {
620             if (isAbandonedConfig()) {
621                 return;
622             }
623             throw new IllegalStateException(
624                     "Invalidated object not currently part of this pool");
625         }
626         synchronized (p) {
627             if (p.getState() != PooledObjectState.INVALID) {
628                 destroy(p);
629             }
630         }
631         ensureIdle(1, false);
632     }
633
634     /**
635      * Clears any objects sitting idle in the pool by removing them from the
636      * idle instance pool and then invoking the configured
637      * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
638      * idle instance.
639      * <p>
640      * Implementation notes:
641      * </p>
642      * <ul>
643      * <li>This method does not destroy or effect in any way instances that are
644      * checked out of the pool when it is invoked.</li>
645      * <li>Invoking this method does not prevent objects being returned to the
646      * idle instance pool, even during its execution. Additional instances may
647      * be returned while removed items are being destroyed.</li>
648      * <li>Exceptions encountered destroying idle instances are swallowed
649      * but notified via a
650      * {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.</li>
651      * </ul>
652      */

653     @Override
654     public void clear() {
655         PooledObject<T> p = idleObjects.poll();
656
657         while (p != null) {
658             try {
659                 destroy(p);
660             } catch (final Exception e) {
661                 swallowException(e);
662             }
663             p = idleObjects.poll();
664         }
665     }
666
667     @Override
668     public int getNumActive() {
669         return allObjects.size() - idleObjects.size();
670     }
671
672     @Override
673     public int getNumIdle() {
674         return idleObjects.size();
675     }
676
677     /**
678      * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
679      * fail with IllegalStateException, but {@link #returnObject(Object)} and
680      * {@link #invalidateObject(Object)} will continue to work, with returned
681      * objects destroyed on return.
682      * <p>
683      * Destroys idle instances in the pool by invoking {@link #clear()}.
684      * </p>
685      */

686     @Override
687     public void close() {
688         if (isClosed()) {
689             return;
690         }
691
692         synchronized (closeLock) {
693             if (isClosed()) {
694                 return;
695             }
696
697             // Stop the evictor before the pool is closed since evict() calls
698             // assertOpen()
699             stopEvictor();
700
701             closed = true;
702             // This clear removes any idle objects
703             clear();
704
705             jmxUnregister();
706
707             // Release any threads that were waiting for an object
708             idleObjects.interuptTakeWaiters();
709         }
710     }
711
712     /**
713      * {@inheritDoc}
714      * <p>
715      * Successive activations of this method examine objects in sequence,
716      * cycling through objects in oldest-to-youngest order.
717      * </p>
718      */

719     @Override
720     public void evict() throws Exception {
721         assertOpen();
722
723         if (idleObjects.size() > 0) {
724
725             PooledObject<T> underTest = null;
726             final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
727
728             synchronized (evictionLock) {
729                 final EvictionConfig evictionConfig = new EvictionConfig(
730                         getMinEvictableIdleTimeMillis(),
731                         getSoftMinEvictableIdleTimeMillis(),
732                         getMinIdle());
733
734                 final boolean testWhileIdle = getTestWhileIdle();
735
736                 for (int i = 0, m = getNumTests(); i < m; i++) {
737                     if (evictionIterator == null || !evictionIterator.hasNext()) {
738                         evictionIterator = new EvictionIterator(idleObjects);
739                     }
740                     if (!evictionIterator.hasNext()) {
741                         // Pool exhausted, nothing to do here
742                         return;
743                     }
744
745                     try {
746                         underTest = evictionIterator.next();
747                     } catch (final NoSuchElementException nsee) {
748                         // Object was borrowed in another thread
749                         // Don't count this as an eviction test so reduce i;
750                         i--;
751                         evictionIterator = null;
752                         continue;
753                     }
754
755                     if (!underTest.startEvictionTest()) {
756                         // Object was borrowed in another thread
757                         // Don't count this as an eviction test so reduce i;
758                         i--;
759                         continue;
760                     }
761
762                     // User provided eviction policy could throw all sorts of
763                     // crazy exceptions. Protect against such an exception
764                     // killing the eviction thread.
765                     boolean evict;
766                     try {
767                         evict = evictionPolicy.evict(evictionConfig, underTest,
768                                 idleObjects.size());
769                     } catch (final Throwable t) {
770                         // Slightly convoluted as SwallowedExceptionListener
771                         // uses Exception rather than Throwable
772                         PoolUtils.checkRethrow(t);
773                         swallowException(new Exception(t));
774                         // Don't evict on error conditions
775                         evict = false;
776                     }
777
778                     if (evict) {
779                         destroy(underTest);
780                         destroyedByEvictorCount.incrementAndGet();
781                     } else {
782                         if (testWhileIdle) {
783                             boolean active = false;
784                             try {
785                                 factory.activateObject(underTest);
786                                 active = true;
787                             } catch (final Exception e) {
788                                 destroy(underTest);
789                                 destroyedByEvictorCount.incrementAndGet();
790                             }
791                             if (active) {
792                                 if (!factory.validateObject(underTest)) {
793                                     destroy(underTest);
794                                     destroyedByEvictorCount.incrementAndGet();
795                                 } else {
796                                     try {
797                                         factory.passivateObject(underTest);
798                                     } catch (final Exception e) {
799                                         destroy(underTest);
800                                         destroyedByEvictorCount.incrementAndGet();
801                                     }
802                                 }
803                             }
804                         }
805                         if (!underTest.endEvictionTest(idleObjects)) {
806                             // TODO - May need to add code here once additional
807                             // states are used
808                         }
809                     }
810                 }
811             }
812         }
813         final AbandonedConfig ac = this.abandonedConfig;
814         if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
815             removeAbandoned(ac);
816         }
817     }
818
819     /**
820      * Tries to ensure that {@link #getMinIdle()} idle instances are available
821      * in the pool.
822      *
823      * @throws Exception If the associated factory throws an exception
824      * @since 2.4
825      */

826     public void preparePool() throws Exception {
827         if (getMinIdle() < 1) {
828             return;
829         }
830         ensureMinIdle();
831     }
832
833     /**
834      * Attempts to create a new wrapped pooled object.
835      * <p>
836      * If there are {@link #getMaxTotal()} objects already in circulation
837      * or in process of being created, this method returns null.
838      * </p>
839      *
840      * @return The new wrapped pooled object
841      *
842      * @throws Exception if the object factory's {@code makeObject} fails
843      */

844     private PooledObject<T> create() throws Exception {
845         int localMaxTotal = getMaxTotal();
846         // This simplifies the code later in this method
847         if (localMaxTotal < 0) {
848             localMaxTotal = Integer.MAX_VALUE;
849         }
850
851         final long localStartTimeMillis = System.currentTimeMillis();
852         final long localMaxWaitTimeMillis = Math.max(getMaxWaitMillis(), 0);
853
854         // Flag that indicates if create should:
855         // - TRUE:  call the factory to create an object
856         // - FALSE: return null
857         // - null:  loop and re-test the condition that determines whether to
858         //          call the factory
859         Boolean create = null;
860         while (create == null) {
861             synchronized (makeObjectCountLock) {
862                 final long newCreateCount = createCount.incrementAndGet();
863                 if (newCreateCount > localMaxTotal) {
864                     // The pool is currently at capacity or in the process of
865                     // making enough new objects to take it to capacity.
866                     createCount.decrementAndGet();
867                     if (makeObjectCount == 0) {
868                         // There are no makeObject() calls in progress so the
869                         // pool is at capacity. Do not attempt to create a new
870                         // object. Return and wait for an object to be returned
871                         create = Boolean.FALSE;
872                     } else {
873                         // There are makeObject() calls in progress that might
874                         // bring the pool to capacity. Those calls might also
875                         // fail so wait until they complete and then re-test if
876                         // the pool is at capacity or not.
877                         makeObjectCountLock.wait(localMaxWaitTimeMillis);
878                     }
879                 } else {
880                     // The pool is not at capacity. Create a new object.
881                     makeObjectCount++;
882                     create = Boolean.TRUE;
883                 }
884             }
885
886             // Do not block more if maxWaitTimeMillis is set.
887             if (create == null &&
888                 (localMaxWaitTimeMillis > 0 &&
889                  System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) {
890                 create = Boolean.FALSE;
891             }
892         }
893
894         if (!create.booleanValue()) {
895             return null;
896         }
897
898         final PooledObject<T> p;
899         try {
900             p = factory.makeObject();
901             if (getTestOnCreate() && !factory.validateObject(p)) {
902                 createCount.decrementAndGet();
903                 return null;
904             }
905         } catch (final Throwable e) {
906             createCount.decrementAndGet();
907             throw e;
908         } finally {
909             synchronized (makeObjectCountLock) {
910                 makeObjectCount--;
911                 makeObjectCountLock.notifyAll();
912             }
913         }
914
915         final AbandonedConfig ac = this.abandonedConfig;
916         if (ac != null && ac.getLogAbandoned()) {
917             p.setLogAbandoned(true);
918             p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
919         }
920
921         createdCount.incrementAndGet();
922         allObjects.put(new IdentityWrapper<>(p.getObject()), p);
923         return p;
924     }
925
926     /**
927      * Destroys a wrapped pooled object.
928      *
929      * @param toDestroy The wrapped pooled object to destroy
930      *
931      * @throws Exception If the factory fails to destroy the pooled object
932      *                   cleanly
933      */

934     private void destroy(final PooledObject<T> toDestroy) throws Exception {
935         toDestroy.invalidate();
936         idleObjects.remove(toDestroy);
937         allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
938         try {
939             factory.destroyObject(toDestroy);
940         } finally {
941             destroyedCount.incrementAndGet();
942             createCount.decrementAndGet();
943         }
944     }
945
946     @Override
947     void ensureMinIdle() throws Exception {
948         ensureIdle(getMinIdle(), true);
949     }
950
951     /**
952      * Tries to ensure that {@code idleCount} idle instances exist in the pool.
953      * <p>
954      * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
955      * or the total number of objects (idle, checked out, or being created) reaches
956      * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
957      * there are threads waiting to check out instances from the pool.
958      * </p>
959      *
960      * @param idleCount the number of idle instances desired
961      * @param always true means create instances even if the pool has no threads waiting
962      * @throws Exception if the factory's makeObject throws
963      */

964     private void ensureIdle(final int idleCount, final boolean always) throws Exception {
965         if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
966             return;
967         }
968
969         while (idleObjects.size() < idleCount) {
970             final PooledObject<T> p = create();
971             if (p == null) {
972                 // Can't create objects, no reason to think another call to
973                 // create will work. Give up.
974                 break;
975             }
976             if (getLifo()) {
977                 idleObjects.addFirst(p);
978             } else {
979                 idleObjects.addLast(p);
980             }
981         }
982         if (isClosed()) {
983             // Pool closed while object was being added to idle objects.
984             // Make sure the returned object is destroyed rather than left
985             // in the idle object pool (which would effectively be a leak)
986             clear();
987         }
988     }
989
990     /**
991      * Creates an object, and place it into the pool. addObject() is useful for
992      * "pre-loading" a pool with idle objects.
993      * <p>
994      * If there is no capacity available to add to the pool, this is a no-op
995      * (no exception, no impact to the pool). </p>
996      */

997     @Override
998     public void addObject() throws Exception {
999         assertOpen();
1000         if (factory == null) {
1001             throw new IllegalStateException(
1002                     "Cannot add objects without a factory.");
1003         }
1004         final PooledObject<T> p = create();
1005         addIdleObject(p);
1006     }
1007
1008     /**
1009      * Adds the provided wrapped pooled object to the set of idle objects for
1010      * this pool. The object must already be part of the pool.  If {@code p}
1011      * is nullthis is a no-op (no exception, but no impact on the pool).
1012      *
1013      * @param p The object to make idle
1014      *
1015      * @throws Exception If the factory fails to passivate the object
1016      */

1017     private void addIdleObject(final PooledObject<T> p) throws Exception {
1018         if (p != null) {
1019             factory.passivateObject(p);
1020             if (getLifo()) {
1021                 idleObjects.addFirst(p);
1022             } else {
1023                 idleObjects.addLast(p);
1024             }
1025         }
1026     }
1027
1028     /**
1029      * Calculates the number of objects to test in a run of the idle object
1030      * evictor.
1031      *
1032      * @return The number of objects to test for validity
1033      */

1034     private int getNumTests() {
1035         final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
1036         if (numTestsPerEvictionRun >= 0) {
1037             return Math.min(numTestsPerEvictionRun, idleObjects.size());
1038         }
1039         return (int) (Math.ceil(idleObjects.size() /
1040                 Math.abs((double) numTestsPerEvictionRun)));
1041     }
1042
1043     /**
1044      * Recovers abandoned objects which have been checked out but
1045      * not used since longer than the removeAbandonedTimeout.
1046      *
1047      * @param ac The configuration to use to identify abandoned objects
1048      */

1049     private void removeAbandoned(final AbandonedConfig ac) {
1050         // Generate a list of abandoned objects to remove
1051         final long now = System.currentTimeMillis();
1052         final long timeout =
1053                 now - (ac.getRemoveAbandonedTimeout() * 1000L);
1054         final ArrayList<PooledObject<T>> remove = new ArrayList<>();
1055         final Iterator<PooledObject<T>> it = allObjects.values().iterator();
1056         while (it.hasNext()) {
1057             final PooledObject<T> pooledObject = it.next();
1058             synchronized (pooledObject) {
1059                 if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
1060                         pooledObject.getLastUsedTime() <= timeout) {
1061                     pooledObject.markAbandoned();
1062                     remove.add(pooledObject);
1063                 }
1064             }
1065         }
1066
1067         // Now remove the abandoned objects
1068         final Iterator<PooledObject<T>> itr = remove.iterator();
1069         while (itr.hasNext()) {
1070             final PooledObject<T> pooledObject = itr.next();
1071             if (ac.getLogAbandoned()) {
1072                 pooledObject.printStackTrace(ac.getLogWriter());
1073             }
1074             try {
1075                 invalidateObject(pooledObject.getObject());
1076             } catch (final Exception e) {
1077                 e.printStackTrace();
1078             }
1079         }
1080     }
1081
1082
1083     //--- Usage tracking support -----------------------------------------------
1084
1085     @Override
1086     public void use(final T pooledObject) {
1087         final AbandonedConfig ac = this.abandonedConfig;
1088         if (ac != null && ac.getUseUsageTracking()) {
1089             final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
1090             wrapper.use();
1091         }
1092     }
1093
1094
1095     //--- JMX support ----------------------------------------------------------
1096
1097     private volatile String factoryType = null;
1098
1099     /**
1100      * Returns an estimate of the number of threads currently blocked waiting for
1101      * an object from the pool. This is intended for monitoring only, not for
1102      * synchronization control.
1103      *
1104      * @return The estimate of the number of threads currently blocked waiting
1105      *         for an object from the pool
1106      */

1107     @Override
1108     public int getNumWaiters() {
1109         if (getBlockWhenExhausted()) {
1110             return idleObjects.getTakeQueueLength();
1111         }
1112         return 0;
1113     }
1114
1115     /**
1116      * Returns the type - including the specific type rather than the generic -
1117      * of the factory.
1118      *
1119      * @return A string representation of the factory type
1120      */

1121     @Override
1122     public String getFactoryType() {
1123         // Not thread safe. Accept that there may be multiple evaluations.
1124         if (factoryType == null) {
1125             final StringBuilder result = new StringBuilder();
1126             result.append(factory.getClass().getName());
1127             result.append('<');
1128             final Class<?> pooledObjectType =
1129                     PoolImplUtils.getFactoryType(factory.getClass());
1130             result.append(pooledObjectType.getName());
1131             result.append('>');
1132             factoryType = result.toString();
1133         }
1134         return factoryType;
1135     }
1136
1137     /**
1138      * Provides information on all the objects in the pool, both idle (waiting
1139      * to be borrowed) and active (currently borrowed).
1140      * <p>
1141      * Note: This is named listAllObjects so it is presented as an operation via
1142      * JMX. That means it won't be invoked unless the explicitly requested
1143      * whereas all attributes will be automatically requested when viewing the
1144      * attributes for an object in a tool like JConsole.
1145      * </p>
1146      *
1147      * @return Information grouped on all the objects in the pool
1148      */

1149     @Override
1150     public Set<DefaultPooledObjectInfo> listAllObjects() {
1151         final Set<DefaultPooledObjectInfo> result =
1152                 new HashSet<>(allObjects.size());
1153         for (final PooledObject<T> p : allObjects.values()) {
1154             result.add(new DefaultPooledObjectInfo(p));
1155         }
1156         return result;
1157     }
1158
1159     // --- configuration attributes --------------------------------------------
1160
1161     private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
1162     private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
1163     private final PooledObjectFactory<T> factory;
1164
1165
1166     // --- internal attributes -------------------------------------------------
1167
1168     /*
1169      * All of the objects currently associated with this pool in any state. It
1170      * excludes objects that have been destroyed. The size of
1171      * {@link #allObjects} will always be less than or equal to {@link
1172      * #_maxActive}. Map keys are pooled objects, values are the PooledObject
1173      * wrappers used internally by the pool.
1174      */

1175     private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
1176         new ConcurrentHashMap<>();
1177     /*
1178      * The combined count of the currently created objects and those in the
1179      * process of being created. Under load, it may exceed {@link #_maxActive}
1180      * if multiple threads try and create a new object at the same time but
1181      * {@link #create()} will ensure that there are never more than
1182      * {@link #_maxActive} objects created at any one time.
1183      */

1184     private final AtomicLong createCount = new AtomicLong(0);
1185     private long makeObjectCount = 0;
1186     private final Object makeObjectCountLock = new Object();
1187     private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
1188
1189     // JMX specific attributes
1190     private static final String ONAME_BASE =
1191         "org.apache.tomcat.dbcp.pool2:type=GenericObjectPool,name=";
1192
1193     // Additional configuration properties for abandoned object tracking
1194     private volatile AbandonedConfig abandonedConfig = null;
1195
1196     @Override
1197     protected void toStringAppendFields(final StringBuilder builder) {
1198         super.toStringAppendFields(builder);
1199         builder.append(", factoryType=");
1200         builder.append(factoryType);
1201         builder.append(", maxIdle=");
1202         builder.append(maxIdle);
1203         builder.append(", minIdle=");
1204         builder.append(minIdle);
1205         builder.append(", factory=");
1206         builder.append(factory);
1207         builder.append(", allObjects=");
1208         builder.append(allObjects);
1209         builder.append(", createCount=");
1210         builder.append(createCount);
1211         builder.append(", idleObjects=");
1212         builder.append(idleObjects);
1213         builder.append(", abandonedConfig=");
1214         builder.append(abandonedConfig);
1215     }
1216
1217 }
1218