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