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