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