001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.pool2.impl;
018
019import org.apache.commons.pool2.ObjectPool;
020import org.apache.commons.pool2.PoolUtils;
021import org.apache.commons.pool2.PooledObject;
022import org.apache.commons.pool2.PooledObjectFactory;
023import org.apache.commons.pool2.PooledObjectState;
024import org.apache.commons.pool2.SwallowedExceptionListener;
025import org.apache.commons.pool2.TrackedUse;
026import org.apache.commons.pool2.UsageTracking;
027
028import java.util.ArrayList;
029import java.util.HashSet;
030import java.util.Iterator;
031import java.util.Map;
032import java.util.NoSuchElementException;
033import java.util.Set;
034import java.util.concurrent.ConcurrentHashMap;
035import java.util.concurrent.TimeUnit;
036import java.util.concurrent.atomic.AtomicLong;
037
038/**
039 * A configurable {@link ObjectPool} implementation.
040 * <p>
041 * When coupled with the appropriate {@link PooledObjectFactory},
042 * <code>GenericObjectPool</code> provides robust pooling functionality for
043 * arbitrary objects.</p>
044 * <p>
045 * Optionally, one may configure the pool to examine and possibly evict objects
046 * as they sit idle in the pool and to ensure that a minimum number of idle
047 * objects are available. This is performed by an "idle object eviction" thread,
048 * which runs asynchronously. Caution should be used when configuring this
049 * optional feature. Eviction runs contend with client threads for access to
050 * objects in the pool, so if they run too frequently performance issues may
051 * result.</p>
052 * <p>
053 * The pool can also be configured to detect and remove "abandoned" objects,
054 * i.e. objects that have been checked out of the pool but neither used nor
055 * returned before the configured
056 * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}.
057 * Abandoned object removal can be configured to happen when
058 * <code>borrowObject</code> is invoked and the pool is close to starvation, or
059 * it can be executed by the idle object evictor, or both. If pooled objects
060 * implement the {@link TrackedUse} interface, their last use will be queried
061 * using the <code>getLastUsed</code> method on that interface; otherwise
062 * abandonment is determined by how long an object has been checked out from
063 * the pool.</p>
064 * <p>
065 * Implementation note: To prevent possible deadlocks, care has been taken to
066 * ensure that no call to a factory method will occur within a synchronization
067 * block. See POOL-125 and DBCP-44 for more information.</p>
068 * <p>
069 * This class is intended to be thread-safe.</p>
070 *
071 * @see GenericKeyedObjectPool
072 *
073 * @param <T> Type of element pooled in this pool.
074 *
075 * @since 2.0
076 */
077public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
078        implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {
079
080    /**
081     * Creates a new <code>GenericObjectPool</code> using defaults from
082     * {@link GenericObjectPoolConfig}.
083     *
084     * @param factory The object factory to be used to create object instances
085     *                used by this pool
086     */
087    public GenericObjectPool(final PooledObjectFactory<T> factory) {
088        this(factory, new GenericObjectPoolConfig<T>());
089    }
090
091    /**
092     * Creates a new <code>GenericObjectPool</code> using a specific
093     * configuration.
094     *
095     * @param factory   The object factory to be used to create object instances
096     *                  used by this pool
097     * @param config    The configuration to use for this pool instance. The
098     *                  configuration is used by value. Subsequent changes to
099     *                  the configuration object will not be reflected in the
100     *                  pool.
101     */
102    public GenericObjectPool(final PooledObjectFactory<T> factory,
103            final GenericObjectPoolConfig<T> config) {
104
105        super(config, ONAME_BASE, config.getJmxNamePrefix());
106
107        if (factory == null) {
108            jmxUnregister(); // tidy up
109            throw new IllegalArgumentException("factory may not be null");
110        }
111        this.factory = factory;
112
113        idleObjects = new LinkedBlockingDeque<>(config.getFairness());
114
115        setConfig(config);
116    }
117
118    /**
119     * Creates a new <code>GenericObjectPool</code> that tracks and destroys
120     * objects that are checked out, but never returned to the pool.
121     *
122     * @param factory   The object factory to be used to create object instances
123     *                  used by this pool
124     * @param config    The base pool configuration to use for this pool instance.
125     *                  The configuration is used by value. Subsequent changes to
126     *                  the configuration object will not be reflected in the
127     *                  pool.
128     * @param abandonedConfig  Configuration for abandoned object identification
129     *                         and removal.  The configuration is used by value.
130     */
131    public GenericObjectPool(final PooledObjectFactory<T> factory,
132            final GenericObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
133        this(factory, config);
134        setAbandonedConfig(abandonedConfig);
135    }
136
137    /**
138     * Returns the cap on the number of "idle" instances in the pool. If maxIdle
139     * is set too low on heavily loaded systems it is possible you will see
140     * objects being destroyed and almost immediately new objects being created.
141     * This is a result of the active threads momentarily returning objects
142     * faster than they are requesting them, causing the number of idle
143     * objects to rise above maxIdle. The best value for maxIdle for heavily
144     * loaded system will vary but the default is a good starting point.
145     *
146     * @return the maximum number of "idle" instances that can be held in the
147     *         pool or a negative value if there is no limit
148     *
149     * @see #setMaxIdle
150     */
151    @Override
152    public int getMaxIdle() {
153        return maxIdle;
154    }
155
156    /**
157     * Returns the cap on the number of "idle" instances in the pool. If maxIdle
158     * is set too low on heavily loaded systems it is possible you will see
159     * objects being destroyed and almost immediately new objects being created.
160     * This is a result of the active threads momentarily returning objects
161     * faster than they are requesting them, causing the number of idle
162     * objects to rise above maxIdle. The best value for maxIdle for heavily
163     * loaded system will vary but the default is a good starting point.
164     *
165     * @param maxIdle
166     *            The cap on the number of "idle" instances in the pool. Use a
167     *            negative value to indicate an unlimited number of idle
168     *            instances
169     *
170     * @see #getMaxIdle
171     */
172    public void setMaxIdle(final int maxIdle) {
173        this.maxIdle = maxIdle;
174    }
175
176    /**
177     * Sets the target for the minimum number of idle objects to maintain in
178     * the pool. This setting only has an effect if it is positive and
179     * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
180     * is the case, an attempt is made to ensure that the pool has the required
181     * minimum number of instances during idle object eviction runs.
182     * <p>
183     * If the configured value of minIdle is greater than the configured value
184     * for maxIdle then the value of maxIdle will be used instead.
185     * </p>
186     *
187     * @param minIdle
188     *            The minimum number of objects.
189     *
190     * @see #getMinIdle()
191     * @see #getMaxIdle()
192     * @see #getTimeBetweenEvictionRunsMillis()
193     */
194    public void setMinIdle(final int minIdle) {
195        this.minIdle = minIdle;
196    }
197
198    /**
199     * Returns the target for the minimum number of idle objects to maintain in
200     * the pool. This setting only has an effect if it is positive and
201     * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
202     * is the case, an attempt is made to ensure that the pool has the required
203     * minimum number of instances during idle object eviction runs.
204     * <p>
205     * If the configured value of minIdle is greater than the configured value
206     * for maxIdle then the value of maxIdle will be used instead.
207     * </p>
208     *
209     * @return The minimum number of objects.
210     *
211     * @see #setMinIdle(int)
212     * @see #setMaxIdle(int)
213     * @see #setTimeBetweenEvictionRunsMillis(long)
214     */
215    @Override
216    public int getMinIdle() {
217        final int maxIdleSave = getMaxIdle();
218        if (this.minIdle > maxIdleSave) {
219            return maxIdleSave;
220        }
221        return minIdle;
222    }
223
224    /**
225     * Gets whether or not abandoned object removal is configured for this pool.
226     *
227     * @return true if this pool is configured to detect and remove
228     * abandoned objects
229     */
230    @Override
231    public boolean isAbandonedConfig() {
232        return abandonedConfig != null;
233    }
234
235    /**
236     * Gets whether this pool identifies and logs any abandoned objects.
237     *
238     * @return {@code true} if abandoned object removal is configured for this
239     *         pool and removal events are to be logged otherwise {@code false}
240     *
241     * @see AbandonedConfig#getLogAbandoned()
242     */
243    @Override
244    public boolean getLogAbandoned() {
245        final AbandonedConfig ac = this.abandonedConfig;
246        return ac != null && ac.getLogAbandoned();
247    }
248
249    /**
250     * Gets whether a check is made for abandoned objects when an object is borrowed
251     * from this pool.
252     *
253     * @return {@code true} if abandoned object removal is configured to be
254     *         activated by borrowObject otherwise {@code false}
255     *
256     * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
257     */
258    @Override
259    public boolean getRemoveAbandonedOnBorrow() {
260        final AbandonedConfig ac = this.abandonedConfig;
261        return ac != null && ac.getRemoveAbandonedOnBorrow();
262    }
263
264    /**
265     * Gets whether a check is made for abandoned objects when the evictor runs.
266     *
267     * @return {@code true} if abandoned object removal is configured to be
268     *         activated when the evictor runs otherwise {@code false}
269     *
270     * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
271     */
272    @Override
273    public boolean getRemoveAbandonedOnMaintenance() {
274        final AbandonedConfig ac = this.abandonedConfig;
275        return ac != null && ac.getRemoveAbandonedOnMaintenance();
276    }
277
278    /**
279     * Obtains the timeout before which an object will be considered to be
280     * abandoned by this pool.
281     *
282     * @return The abandoned object timeout in seconds if abandoned object
283     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
284     *
285     * @see AbandonedConfig#getRemoveAbandonedTimeout()
286     */
287    @Override
288    public int getRemoveAbandonedTimeout() {
289        final AbandonedConfig ac = this.abandonedConfig;
290        return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
291    }
292
293
294    /**
295     * Sets the base pool configuration.
296     *
297     * @param conf the new configuration to use. This is used by value.
298     *
299     * @see GenericObjectPoolConfig
300     */
301    public void setConfig(final GenericObjectPoolConfig<T> conf) {
302        super.setConfig(conf);
303        setMaxIdle(conf.getMaxIdle());
304        setMinIdle(conf.getMinIdle());
305        setMaxTotal(conf.getMaxTotal());
306    }
307
308    /**
309     * Sets the abandoned object removal configuration.
310     *
311     * @param abandonedConfig the new configuration to use. This is used by value.
312     *
313     * @see AbandonedConfig
314     */
315    public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
316        if (abandonedConfig == null) {
317            this.abandonedConfig = null;
318        } else {
319            this.abandonedConfig = new AbandonedConfig();
320            this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
321            this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
322            this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
323            this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance());
324            this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
325            this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
326            this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace());
327        }
328    }
329
330    /**
331     * Obtains a reference to the factory used to create, destroy and validate
332     * the objects used by this pool.
333     *
334     * @return the factory
335     */
336    public PooledObjectFactory<T> getFactory() {
337        return factory;
338    }
339
340    /**
341     * Equivalent to <code>{@link #borrowObject(long)
342     * borrowObject}({@link #getMaxWaitMillis()})</code>.
343     * <p>
344     * {@inheritDoc}
345     * </p>
346     */
347    @Override
348    public T borrowObject() throws Exception {
349        return borrowObject(getMaxWaitMillis());
350    }
351
352    /**
353     * Borrows an object from the pool using the specific waiting time which only
354     * applies if {@link #getBlockWhenExhausted()} is true.
355     * <p>
356     * If there is one or more idle instance available in the pool, then an
357     * idle instance will be selected based on the value of {@link #getLifo()},
358     * activated and returned. If activation fails, or {@link #getTestOnBorrow()
359     * testOnBorrow} is set to <code>true</code> and validation fails, the
360     * instance is destroyed and the next available instance is examined. This
361     * continues until either a valid instance is returned or there are no more
362     * idle instances available.
363     * </p>
364     * <p>
365     * If there are no idle instances available in the pool, behavior depends on
366     * the {@link #getMaxTotal() maxTotal}, (if applicable)
367     * {@link #getBlockWhenExhausted()} and the value passed in to the
368     * <code>borrowMaxWaitMillis</code> parameter. If the number of instances
369     * checked out from the pool is less than <code>maxTotal,</code> a new
370     * instance is created, activated and (if applicable) validated and returned
371     * to the caller. If validation fails, a <code>NoSuchElementException</code>
372     * is thrown.
373     * </p>
374     * <p>
375     * If the pool is exhausted (no available idle instances and no capacity to
376     * create new ones), this method will either block (if
377     * {@link #getBlockWhenExhausted()} is true) or throw a
378     * <code>NoSuchElementException</code> (if
379     * {@link #getBlockWhenExhausted()} is false). The length of time that this
380     * method will block when {@link #getBlockWhenExhausted()} is true is
381     * determined by the value passed in to the <code>borrowMaxWaitMillis</code>
382     * parameter.
383     * </p>
384     * <p>
385     * When the pool is exhausted, multiple calling threads may be
386     * simultaneously blocked waiting for instances to become available. A
387     * "fairness" algorithm has been implemented to ensure that threads receive
388     * available instances in request arrival order.
389     * </p>
390     *
391     * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
392     *                            to become available
393     *
394     * @return object instance from the pool
395     *
396     * @throws NoSuchElementException if an instance cannot be returned
397     *
398     * @throws Exception if an object instance cannot be returned due to an
399     *                   error
400     */
401    public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
402        assertOpen();
403
404        final AbandonedConfig ac = this.abandonedConfig;
405        if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
406                (getNumIdle() < 2) &&
407                (getNumActive() > getMaxTotal() - 3) ) {
408            removeAbandoned(ac);
409        }
410
411        PooledObject<T> p = null;
412
413        // Get local copy of current config so it is consistent for entire
414        // method execution
415        final boolean blockWhenExhausted = getBlockWhenExhausted();
416
417        boolean create;
418        final long waitTime = System.currentTimeMillis();
419
420        while (p == null) {
421            create = false;
422            p = idleObjects.pollFirst();
423            if (p == null) {
424                p = create();
425                if (p != null) {
426                    create = true;
427                }
428            }
429            if (blockWhenExhausted) {
430                if (p == null) {
431                    if (borrowMaxWaitMillis < 0) {
432                        p = idleObjects.takeFirst();
433                    } else {
434                        p = idleObjects.pollFirst(borrowMaxWaitMillis,
435                                TimeUnit.MILLISECONDS);
436                    }
437                }
438                if (p == null) {
439                    throw new NoSuchElementException(
440                            "Timeout waiting for idle object");
441                }
442            } else {
443                if (p == null) {
444                    throw new NoSuchElementException("Pool exhausted");
445                }
446            }
447            if (!p.allocate()) {
448                p = null;
449            }
450
451            if (p != null) {
452                try {
453                    factory.activateObject(p);
454                } catch (final Exception e) {
455                    try {
456                        destroy(p);
457                    } catch (final Exception e1) {
458                        // Ignore - activation failure is more important
459                    }
460                    p = null;
461                    if (create) {
462                        final NoSuchElementException nsee = new NoSuchElementException(
463                                "Unable to activate object");
464                        nsee.initCause(e);
465                        throw nsee;
466                    }
467                }
468                if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
469                    boolean validate = false;
470                    Throwable validationThrowable = null;
471                    try {
472                        validate = factory.validateObject(p);
473                    } catch (final Throwable t) {
474                        PoolUtils.checkRethrow(t);
475                        validationThrowable = t;
476                    }
477                    if (!validate) {
478                        try {
479                            destroy(p);
480                            destroyedByBorrowValidationCount.incrementAndGet();
481                        } catch (final Exception e) {
482                            // Ignore - validation failure is more important
483                        }
484                        p = null;
485                        if (create) {
486                            final NoSuchElementException nsee = new NoSuchElementException(
487                                    "Unable to validate object");
488                            nsee.initCause(validationThrowable);
489                            throw nsee;
490                        }
491                    }
492                }
493            }
494        }
495
496        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
497
498        return p.getObject();
499    }
500
501    /**
502     * {@inheritDoc}
503     * <p>
504     * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
505     * number of idle instances has reached this value, the returning instance
506     * is destroyed.
507     * </p>
508     * <p>
509     * If {@link #getTestOnReturn() testOnReturn} == true, the returning
510     * instance is validated before being returned to the idle instance pool. In
511     * this case, if validation fails, the instance is destroyed.
512     * </p>
513     * <p>
514     * Exceptions encountered destroying objects for any reason are swallowed
515     * but notified via a {@link SwallowedExceptionListener}.
516     * </p>
517     */
518    @Override
519    public void returnObject(final T obj) {
520        final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
521
522        if (p == null) {
523            if (!isAbandonedConfig()) {
524                throw new IllegalStateException(
525                        "Returned object not currently part of this pool");
526            }
527            return; // Object was abandoned and removed
528        }
529
530        markReturningState(p);
531
532        final long activeTime = p.getActiveTimeMillis();
533
534        if (getTestOnReturn() && !factory.validateObject(p)) {
535            try {
536                destroy(p);
537            } catch (final Exception e) {
538                swallowException(e);
539            }
540            try {
541                ensureIdle(1, false);
542            } catch (final Exception e) {
543                swallowException(e);
544            }
545            updateStatsReturn(activeTime);
546            return;
547        }
548
549        try {
550            factory.passivateObject(p);
551        } catch (final Exception e1) {
552            swallowException(e1);
553            try {
554                destroy(p);
555            } catch (final Exception e) {
556                swallowException(e);
557            }
558            try {
559                ensureIdle(1, false);
560            } catch (final Exception e) {
561                swallowException(e);
562            }
563            updateStatsReturn(activeTime);
564            return;
565        }
566
567        if (!p.deallocate()) {
568            throw new IllegalStateException(
569                    "Object has already been returned to this pool or is invalid");
570        }
571
572        final int maxIdleSave = getMaxIdle();
573        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
574            try {
575                destroy(p);
576            } catch (final Exception e) {
577                swallowException(e);
578            }
579        } else {
580            if (getLifo()) {
581                idleObjects.addFirst(p);
582            } else {
583                idleObjects.addLast(p);
584            }
585            if (isClosed()) {
586                // Pool closed while object was being added to idle objects.
587                // Make sure the returned object is destroyed rather than left
588                // in the idle object pool (which would effectively be a leak)
589                clear();
590            }
591        }
592        updateStatsReturn(activeTime);
593    }
594
595    /**
596     * {@inheritDoc}
597     * <p>
598     * Activation of this method decrements the active count and attempts to
599     * destroy the instance.
600     * </p>
601     *
602     * @throws Exception             if an exception occurs destroying the
603     *                               object
604     * @throws IllegalStateException if obj does not belong to this pool
605     */
606    @Override
607    public void invalidateObject(final T obj) throws Exception {
608        final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
609        if (p == null) {
610            if (isAbandonedConfig()) {
611                return;
612            }
613            throw new IllegalStateException(
614                    "Invalidated object not currently part of this pool");
615        }
616        synchronized (p) {
617            if (p.getState() != PooledObjectState.INVALID) {
618                destroy(p);
619            }
620        }
621        ensureIdle(1, false);
622    }
623
624    /**
625     * Clears any objects sitting idle in the pool by removing them from the
626     * idle instance pool and then invoking the configured
627     * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
628     * idle instance.
629     * <p>
630     * Implementation notes:
631     * </p>
632     * <ul>
633     * <li>This method does not destroy or effect in any way instances that are
634     * checked out of the pool when it is invoked.</li>
635     * <li>Invoking this method does not prevent objects being returned to the
636     * idle instance pool, even during its execution. Additional instances may
637     * be returned while removed items are being destroyed.</li>
638     * <li>Exceptions encountered destroying idle instances are swallowed
639     * but notified via a {@link SwallowedExceptionListener}.</li>
640     * </ul>
641     */
642    @Override
643    public void clear() {
644        PooledObject<T> p = idleObjects.poll();
645
646        while (p != null) {
647            try {
648                destroy(p);
649            } catch (final Exception e) {
650                swallowException(e);
651            }
652            p = idleObjects.poll();
653        }
654    }
655
656    @Override
657    public int getNumActive() {
658        return allObjects.size() - idleObjects.size();
659    }
660
661    @Override
662    public int getNumIdle() {
663        return idleObjects.size();
664    }
665
666    /**
667     * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
668     * fail with IllegalStateException, but {@link #returnObject(Object)} and
669     * {@link #invalidateObject(Object)} will continue to work, with returned
670     * objects destroyed on return.
671     * <p>
672     * Destroys idle instances in the pool by invoking {@link #clear()}.
673     * </p>
674     */
675    @Override
676    public void close() {
677        if (isClosed()) {
678            return;
679        }
680
681        synchronized (closeLock) {
682            if (isClosed()) {
683                return;
684            }
685
686            // Stop the evictor before the pool is closed since evict() calls
687            // assertOpen()
688            stopEvitor();
689
690            closed = true;
691            // This clear removes any idle objects
692            clear();
693
694            jmxUnregister();
695
696            // Release any threads that were waiting for an object
697            idleObjects.interuptTakeWaiters();
698        }
699    }
700
701    /**
702     * {@inheritDoc}
703     * <p>
704     * Successive activations of this method examine objects in sequence,
705     * cycling through objects in oldest-to-youngest order.
706     * </p>
707     */
708    @Override
709    public void evict() throws Exception {
710        assertOpen();
711
712        if (idleObjects.size() > 0) {
713
714            PooledObject<T> underTest = null;
715            final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
716
717            synchronized (evictionLock) {
718                final EvictionConfig evictionConfig = new EvictionConfig(
719                        getMinEvictableIdleTimeMillis(),
720                        getSoftMinEvictableIdleTimeMillis(),
721                        getMinIdle());
722
723                final boolean testWhileIdle = getTestWhileIdle();
724
725                for (int i = 0, m = getNumTests(); i < m; i++) {
726                    if (evictionIterator == null || !evictionIterator.hasNext()) {
727                        evictionIterator = new EvictionIterator(idleObjects);
728                    }
729                    if (!evictionIterator.hasNext()) {
730                        // Pool exhausted, nothing to do here
731                        return;
732                    }
733
734                    try {
735                        underTest = evictionIterator.next();
736                    } catch (final NoSuchElementException nsee) {
737                        // Object was borrowed in another thread
738                        // Don't count this as an eviction test so reduce i;
739                        i--;
740                        evictionIterator = null;
741                        continue;
742                    }
743
744                    if (!underTest.startEvictionTest()) {
745                        // Object was borrowed in another thread
746                        // Don't count this as an eviction test so reduce i;
747                        i--;
748                        continue;
749                    }
750
751                    // User provided eviction policy could throw all sorts of
752                    // crazy exceptions. Protect against such an exception
753                    // killing the eviction thread.
754                    boolean evict;
755                    try {
756                        evict = evictionPolicy.evict(evictionConfig, underTest,
757                                idleObjects.size());
758                    } catch (final Throwable t) {
759                        // Slightly convoluted as SwallowedExceptionListener
760                        // uses Exception rather than Throwable
761                        PoolUtils.checkRethrow(t);
762                        swallowException(new Exception(t));
763                        // Don't evict on error conditions
764                        evict = false;
765                    }
766
767                    if (evict) {
768                        destroy(underTest);
769                        destroyedByEvictorCount.incrementAndGet();
770                    } else {
771                        if (testWhileIdle) {
772                            boolean active = false;
773                            try {
774                                factory.activateObject(underTest);
775                                active = true;
776                            } catch (final Exception e) {
777                                destroy(underTest);
778                                destroyedByEvictorCount.incrementAndGet();
779                            }
780                            if (active) {
781                                if (!factory.validateObject(underTest)) {
782                                    destroy(underTest);
783                                    destroyedByEvictorCount.incrementAndGet();
784                                } else {
785                                    try {
786                                        factory.passivateObject(underTest);
787                                    } catch (final Exception e) {
788                                        destroy(underTest);
789                                        destroyedByEvictorCount.incrementAndGet();
790                                    }
791                                }
792                            }
793                        }
794                        if (!underTest.endEvictionTest(idleObjects)) {
795                            // TODO - May need to add code here once additional
796                            // states are used
797                        }
798                    }
799                }
800            }
801        }
802        final AbandonedConfig ac = this.abandonedConfig;
803        if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
804            removeAbandoned(ac);
805        }
806    }
807
808    /**
809     * Tries to ensure that {@link #getMinIdle()} idle instances are available
810     * in the pool.
811     *
812     * @throws Exception If the associated factory throws an exception
813     * @since 2.4
814     */
815    public void preparePool() throws Exception {
816        if (getMinIdle() < 1) {
817            return;
818        }
819        ensureMinIdle();
820    }
821
822    /**
823     * Attempts to create a new wrapped pooled object.
824     * <p>
825     * If there are {@link #getMaxTotal()} objects already in circulation
826     * or in process of being created, this method returns null.
827     * </p>
828     *
829     * @return The new wrapped pooled object
830     *
831     * @throws Exception if the object factory's {@code makeObject} fails
832     */
833    private PooledObject<T> create() throws Exception {
834        int localMaxTotal = getMaxTotal();
835        // This simplifies the code later in this method
836        if (localMaxTotal < 0) {
837            localMaxTotal = Integer.MAX_VALUE;
838        }
839
840        final long localStartTimeMillis = System.currentTimeMillis();
841        final long localMaxWaitTimeMillis = Math.max(getMaxWaitMillis(), 0);
842
843        // Flag that indicates if create should:
844        // - TRUE:  call the factory to create an object
845        // - FALSE: return null
846        // - null:  loop and re-test the condition that determines whether to
847        //          call the factory
848        Boolean create = null;
849        while (create == null) {
850            synchronized (makeObjectCountLock) {
851                final long newCreateCount = createCount.incrementAndGet();
852                if (newCreateCount > localMaxTotal) {
853                    // The pool is currently at capacity or in the process of
854                    // making enough new objects to take it to capacity.
855                    createCount.decrementAndGet();
856                    if (makeObjectCount == 0) {
857                        // There are no makeObject() calls in progress so the
858                        // pool is at capacity. Do not attempt to create a new
859                        // object. Return and wait for an object to be returned
860                        create = Boolean.FALSE;
861                    } else {
862                        // There are makeObject() calls in progress that might
863                        // bring the pool to capacity. Those calls might also
864                        // fail so wait until they complete and then re-test if
865                        // the pool is at capacity or not.
866                        makeObjectCountLock.wait(localMaxWaitTimeMillis);
867                    }
868                } else {
869                    // The pool is not at capacity. Create a new object.
870                    makeObjectCount++;
871                    create = Boolean.TRUE;
872                }
873            }
874
875            // Do not block more if maxWaitTimeMillis is set.
876            if (create == null &&
877                (localMaxWaitTimeMillis > 0 &&
878                 System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) {
879                create = Boolean.FALSE;
880            }
881        }
882
883        if (!create.booleanValue()) {
884            return null;
885        }
886
887        final PooledObject<T> p;
888        try {
889            p = factory.makeObject();
890        } catch (final Throwable e) {
891            createCount.decrementAndGet();
892            throw e;
893        } finally {
894            synchronized (makeObjectCountLock) {
895                makeObjectCount--;
896                makeObjectCountLock.notifyAll();
897            }
898        }
899
900        final AbandonedConfig ac = this.abandonedConfig;
901        if (ac != null && ac.getLogAbandoned()) {
902            p.setLogAbandoned(true);
903            // TODO: in 3.0, this can use the method defined on PooledObject
904            if (p instanceof DefaultPooledObject<?>) {
905                ((DefaultPooledObject<T>) p).setRequireFullStackTrace(ac.getRequireFullStackTrace());
906            }
907        }
908
909        createdCount.incrementAndGet();
910        allObjects.put(new IdentityWrapper<>(p.getObject()), p);
911        return p;
912    }
913
914    /**
915     * Destroys a wrapped pooled object.
916     *
917     * @param toDestroy The wrapped pooled object to destroy
918     *
919     * @throws Exception If the factory fails to destroy the pooled object
920     *                   cleanly
921     */
922    private void destroy(final PooledObject<T> toDestroy) throws Exception {
923        toDestroy.invalidate();
924        idleObjects.remove(toDestroy);
925        allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
926        try {
927            factory.destroyObject(toDestroy);
928        } finally {
929            destroyedCount.incrementAndGet();
930            createCount.decrementAndGet();
931        }
932
933        if (idleObjects.isEmpty() && idleObjects.hasTakeWaiters()) {
934            // POOL-356.
935            // In case there are already threads waiting on something in the pool
936            // (e.g. idleObjects.takeFirst(); then we need to provide them a fresh instance.
937            // Otherwise they will be stuck forever (or until timeout)
938            final PooledObject<T> freshPooled = create();
939            idleObjects.put(freshPooled);
940        }
941    }
942
943    @Override
944    void ensureMinIdle() throws Exception {
945        ensureIdle(getMinIdle(), true);
946    }
947
948    /**
949     * Tries to ensure that {@code idleCount} idle instances exist in the pool.
950     * <p>
951     * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
952     * or the total number of objects (idle, checked out, or being created) reaches
953     * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
954     * there are threads waiting to check out instances from the pool.
955     * </p>
956     *
957     * @param idleCount the number of idle instances desired
958     * @param always true means create instances even if the pool has no threads waiting
959     * @throws Exception if the factory's makeObject throws
960     */
961    private void ensureIdle(final int idleCount, final boolean always) throws Exception {
962        if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
963            return;
964        }
965
966        while (idleObjects.size() < idleCount) {
967            final PooledObject<T> p = create();
968            if (p == null) {
969                // Can't create objects, no reason to think another call to
970                // create will work. Give up.
971                break;
972            }
973            if (getLifo()) {
974                idleObjects.addFirst(p);
975            } else {
976                idleObjects.addLast(p);
977            }
978        }
979        if (isClosed()) {
980            // Pool closed while object was being added to idle objects.
981            // Make sure the returned object is destroyed rather than left
982            // in the idle object pool (which would effectively be a leak)
983            clear();
984        }
985    }
986
987    /**
988     * Creates an object, and place it into the pool. addObject() is useful for
989     * "pre-loading" a pool with idle objects.
990     * <p>
991     * If there is no capacity available to add to the pool, this is a no-op
992     * (no exception, no impact to the pool). </p>
993     */
994    @Override
995    public void addObject() throws Exception {
996        assertOpen();
997        if (factory == null) {
998            throw new IllegalStateException(
999                    "Cannot add objects without a factory.");
1000        }
1001        final PooledObject<T> p = create();
1002        addIdleObject(p);
1003    }
1004
1005    /**
1006     * Adds the provided wrapped pooled object to the set of idle objects for
1007     * this pool. The object must already be part of the pool.  If {@code p}
1008     * is null, this is a no-op (no exception, but no impact on the pool).
1009     *
1010     * @param p The object to make idle
1011     *
1012     * @throws Exception If the factory fails to passivate the object
1013     */
1014    private void addIdleObject(final PooledObject<T> p) throws Exception {
1015        if (p != null) {
1016            factory.passivateObject(p);
1017            if (getLifo()) {
1018                idleObjects.addFirst(p);
1019            } else {
1020                idleObjects.addLast(p);
1021            }
1022        }
1023    }
1024
1025    /**
1026     * Calculates the number of objects to test in a run of the idle object
1027     * evictor.
1028     *
1029     * @return The number of objects to test for validity
1030     */
1031    private int getNumTests() {
1032        final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
1033        if (numTestsPerEvictionRun >= 0) {
1034            return Math.min(numTestsPerEvictionRun, idleObjects.size());
1035        }
1036        return (int) (Math.ceil(idleObjects.size() /
1037                Math.abs((double) numTestsPerEvictionRun)));
1038    }
1039
1040    /**
1041     * Recovers abandoned objects which have been checked out but
1042     * not used since longer than the removeAbandonedTimeout.
1043     *
1044     * @param ac The configuration to use to identify abandoned objects
1045     */
1046    private void removeAbandoned(final AbandonedConfig ac) {
1047        // Generate a list of abandoned objects to remove
1048        final long now = System.currentTimeMillis();
1049        final long timeout =
1050                now - (ac.getRemoveAbandonedTimeout() * 1000L);
1051        final ArrayList<PooledObject<T>> remove = new ArrayList<>();
1052        final Iterator<PooledObject<T>> it = allObjects.values().iterator();
1053        while (it.hasNext()) {
1054            final PooledObject<T> pooledObject = it.next();
1055            synchronized (pooledObject) {
1056                if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
1057                        pooledObject.getLastUsedTime() <= timeout) {
1058                    pooledObject.markAbandoned();
1059                    remove.add(pooledObject);
1060                }
1061            }
1062        }
1063
1064        // Now remove the abandoned objects
1065        final Iterator<PooledObject<T>> itr = remove.iterator();
1066        while (itr.hasNext()) {
1067            final PooledObject<T> pooledObject = itr.next();
1068            if (ac.getLogAbandoned()) {
1069                pooledObject.printStackTrace(ac.getLogWriter());
1070            }
1071            try {
1072                invalidateObject(pooledObject.getObject());
1073            } catch (final Exception e) {
1074                e.printStackTrace();
1075            }
1076        }
1077    }
1078
1079
1080    //--- Usage tracking support -----------------------------------------------
1081
1082    @Override
1083    public void use(final T pooledObject) {
1084        final AbandonedConfig ac = this.abandonedConfig;
1085        if (ac != null && ac.getUseUsageTracking()) {
1086            final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
1087            wrapper.use();
1088        }
1089    }
1090
1091
1092    //--- JMX support ----------------------------------------------------------
1093
1094    private volatile String factoryType = null;
1095
1096    /**
1097     * Returns an estimate of the number of threads currently blocked waiting for
1098     * an object from the pool. This is intended for monitoring only, not for
1099     * synchronization control.
1100     *
1101     * @return The estimate of the number of threads currently blocked waiting
1102     *         for an object from the pool
1103     */
1104    @Override
1105    public int getNumWaiters() {
1106        if (getBlockWhenExhausted()) {
1107            return idleObjects.getTakeQueueLength();
1108        }
1109        return 0;
1110    }
1111
1112    /**
1113     * Returns the type - including the specific type rather than the generic -
1114     * of the factory.
1115     *
1116     * @return A string representation of the factory type
1117     */
1118    @Override
1119    public String getFactoryType() {
1120        // Not thread safe. Accept that there may be multiple evaluations.
1121        if (factoryType == null) {
1122            final StringBuilder result = new StringBuilder();
1123            result.append(factory.getClass().getName());
1124            result.append('<');
1125            final Class<?> pooledObjectType =
1126                    PoolImplUtils.getFactoryType(factory.getClass());
1127            result.append(pooledObjectType.getName());
1128            result.append('>');
1129            factoryType = result.toString();
1130        }
1131        return factoryType;
1132    }
1133
1134    /**
1135     * Provides information on all the objects in the pool, both idle (waiting
1136     * to be borrowed) and active (currently borrowed).
1137     * <p>
1138     * Note: This is named listAllObjects so it is presented as an operation via
1139     * JMX. That means it won't be invoked unless the explicitly requested
1140     * whereas all attributes will be automatically requested when viewing the
1141     * attributes for an object in a tool like JConsole.
1142     * </p>
1143     *
1144     * @return Information grouped on all the objects in the pool
1145     */
1146    @Override
1147    public Set<DefaultPooledObjectInfo> listAllObjects() {
1148        final Set<DefaultPooledObjectInfo> result =
1149                new HashSet<>(allObjects.size());
1150        for (final PooledObject<T> p : allObjects.values()) {
1151            result.add(new DefaultPooledObjectInfo(p));
1152        }
1153        return result;
1154    }
1155
1156    // --- configuration attributes --------------------------------------------
1157
1158    private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
1159    private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
1160    private final PooledObjectFactory<T> factory;
1161
1162
1163    // --- internal attributes -------------------------------------------------
1164
1165    /*
1166     * All of the objects currently associated with this pool in any state. It
1167     * excludes objects that have been destroyed. The size of
1168     * {@link #allObjects} will always be less than or equal to {@link
1169     * #_maxActive}. Map keys are pooled objects, values are the PooledObject
1170     * wrappers used internally by the pool.
1171     */
1172    private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
1173        new ConcurrentHashMap<>();
1174    /*
1175     * The combined count of the currently created objects and those in the
1176     * process of being created. Under load, it may exceed {@link #_maxActive}
1177     * if multiple threads try and create a new object at the same time but
1178     * {@link #create()} will ensure that there are never more than
1179     * {@link #_maxActive} objects created at any one time.
1180     */
1181    private final AtomicLong createCount = new AtomicLong(0);
1182    private long makeObjectCount = 0;
1183    private final Object makeObjectCountLock = new Object();
1184    private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
1185
1186    // JMX specific attributes
1187    private static final String ONAME_BASE =
1188        "org.apache.commons.pool2:type=GenericObjectPool,name=";
1189
1190    // Additional configuration properties for abandoned object tracking
1191    private volatile AbandonedConfig abandonedConfig = null;
1192
1193    @Override
1194    protected void toStringAppendFields(final StringBuilder builder) {
1195        super.toStringAppendFields(builder);
1196        builder.append(", factoryType=");
1197        builder.append(factoryType);
1198        builder.append(", maxIdle=");
1199        builder.append(maxIdle);
1200        builder.append(", minIdle=");
1201        builder.append(minIdle);
1202        builder.append(", factory=");
1203        builder.append(factory);
1204        builder.append(", allObjects=");
1205        builder.append(allObjects);
1206        builder.append(", createCount=");
1207        builder.append(createCount);
1208        builder.append(", idleObjects=");
1209        builder.append(idleObjects);
1210        builder.append(", abandonedConfig=");
1211        builder.append(abandonedConfig);
1212    }
1213
1214}