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