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