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