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