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