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