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