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