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: 1627011 $
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(obj);
538
539        if (!isAbandonedConfig()) {
540            if (p == null) {
541                throw new IllegalStateException(
542                        "Returned object not currently part of this pool");
543            }
544        } else {
545            if (p == null) {
546                return;  // Object was abandoned and removed
547            } else {
548                // Make sure object is not being reclaimed
549                synchronized(p) {
550                    final PooledObjectState state = p.getState();
551                    if (state != PooledObjectState.ALLOCATED) {
552                        throw new IllegalStateException(
553                                "Object has already been returned to this pool or is invalid");
554                    } else {
555                        p.markReturning(); // Keep from being marked abandoned
556                    }
557                }
558            }
559        }
560
561        long activeTime = p.getActiveTimeMillis();
562
563        if (getTestOnReturn()) {
564            if (!factory.validateObject(p)) {
565                try {
566                    destroy(p);
567                } catch (Exception e) {
568                    swallowException(e);
569                }
570                try {
571                    ensureIdle(1, false);
572                } catch (Exception e) {
573                    swallowException(e);
574                }
575                updateStatsReturn(activeTime);
576                return;
577            }
578        }
579
580        try {
581            factory.passivateObject(p);
582        } catch (Exception e1) {
583            swallowException(e1);
584            try {
585                destroy(p);
586            } catch (Exception e) {
587                swallowException(e);
588            }
589            try {
590                ensureIdle(1, false);
591            } catch (Exception e) {
592                swallowException(e);
593            }
594            updateStatsReturn(activeTime);
595            return;
596        }
597
598        if (!p.deallocate()) {
599            throw new IllegalStateException(
600                    "Object has already been returned to this pool or is invalid");
601        }
602
603        int maxIdleSave = getMaxIdle();
604        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
605            try {
606                destroy(p);
607            } catch (Exception e) {
608                swallowException(e);
609            }
610        } else {
611            if (getLifo()) {
612                idleObjects.addFirst(p);
613            } else {
614                idleObjects.addLast(p);
615            }
616            if (isClosed()) {
617                // Pool closed while object was being added to idle objects.
618                // Make sure the returned object is destroyed rather than left
619                // in the idle object pool (which would effectively be a leak)
620                clear();
621            }
622        }
623        updateStatsReturn(activeTime);
624    }
625
626    /**
627     * {@inheritDoc}
628     * <p>
629     * Activation of this method decrements the active count and attempts to
630     * destroy the instance.
631     *
632     * @throws Exception             if an exception occurs destroying the
633     *                               object
634     * @throws IllegalStateException if obj does not belong to this pool
635     */
636    @Override
637    public void invalidateObject(T obj) throws Exception {
638        PooledObject<T> p = allObjects.get(obj);
639        if (p == null) {
640            if (isAbandonedConfig()) {
641                return;
642            } else {
643                throw new IllegalStateException(
644                        "Invalidated object not currently part of this pool");
645            }
646        }
647        synchronized (p) {
648            if (p.getState() != PooledObjectState.INVALID) {
649                destroy(p);
650            }
651        }
652        ensureIdle(1, false);
653    }
654
655    /**
656     * Clears any objects sitting idle in the pool by removing them from the
657     * idle instance pool and then invoking the configured
658     * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
659     * idle instance.
660     * <p>
661     * Implementation notes:
662     * <ul>
663     * <li>This method does not destroy or effect in any way instances that are
664     * checked out of the pool when it is invoked.</li>
665     * <li>Invoking this method does not prevent objects being returned to the
666     * idle instance pool, even during its execution. Additional instances may
667     * be returned while removed items are being destroyed.</li>
668     * <li>Exceptions encountered destroying idle instances are swallowed
669     * but notified via a {@link SwallowedExceptionListener}.</li>
670     * </ul>
671     */
672    @Override
673    public void clear() {
674        PooledObject<T> p = idleObjects.poll();
675
676        while (p != null) {
677            try {
678                destroy(p);
679            } catch (Exception e) {
680                swallowException(e);
681            }
682            p = idleObjects.poll();
683        }
684    }
685
686    @Override
687    public int getNumActive() {
688        return allObjects.size() - idleObjects.size();
689    }
690
691    @Override
692    public int getNumIdle() {
693        return idleObjects.size();
694    }
695
696    /**
697     * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
698     * fail with IllegalStateException, but {@link #returnObject(Object)} and
699     * {@link #invalidateObject(Object)} will continue to work, with returned
700     * objects destroyed on return.
701     * <p>
702     * Destroys idle instances in the pool by invoking {@link #clear()}.
703     */
704    @Override
705    public void close() {
706        if (isClosed()) {
707            return;
708        }
709
710        synchronized (closeLock) {
711            if (isClosed()) {
712                return;
713            }
714
715            // Stop the evictor before the pool is closed since evict() calls
716            // assertOpen()
717            startEvictor(-1L);
718
719            closed = true;
720            // This clear removes any idle objects
721            clear();
722
723            jmxUnregister();
724
725            // Release any threads that were waiting for an object
726            idleObjects.interuptTakeWaiters();
727        }
728    }
729
730    /**
731     * {@inheritDoc}
732     * <p>
733     * Successive activations of this method examine objects in sequence,
734     * cycling through objects in oldest-to-youngest order.
735     */
736    @Override
737    public void evict() throws Exception {
738        assertOpen();
739
740        if (idleObjects.size() > 0) {
741
742            PooledObject<T> underTest = null;
743            EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
744
745            synchronized (evictionLock) {
746                EvictionConfig evictionConfig = new EvictionConfig(
747                        getMinEvictableIdleTimeMillis(),
748                        getSoftMinEvictableIdleTimeMillis(),
749                        getMinIdle());
750
751                boolean testWhileIdle = getTestWhileIdle();
752
753                for (int i = 0, m = getNumTests(); i < m; i++) {
754                    if (evictionIterator == null || !evictionIterator.hasNext()) {
755                        if (getLifo()) {
756                            evictionIterator = idleObjects.descendingIterator();
757                        } else {
758                            evictionIterator = idleObjects.iterator();
759                        }
760                    }
761                    if (!evictionIterator.hasNext()) {
762                        // Pool exhausted, nothing to do here
763                        return;
764                    }
765
766                    try {
767                        underTest = evictionIterator.next();
768                    } catch (NoSuchElementException nsee) {
769                        // Object was borrowed in another thread
770                        // Don't count this as an eviction test so reduce i;
771                        i--;
772                        evictionIterator = null;
773                        continue;
774                    }
775
776                    if (!underTest.startEvictionTest()) {
777                        // Object was borrowed in another thread
778                        // Don't count this as an eviction test so reduce i;
779                        i--;
780                        continue;
781                    }
782
783                    // User provided eviction policy could throw all sorts of
784                    // crazy exceptions. Protect against such an exception
785                    // killing the eviction thread.
786                    boolean evict;
787                    try {
788                        evict = evictionPolicy.evict(evictionConfig, underTest,
789                                idleObjects.size());
790                    } catch (Throwable t) {
791                        // Slightly convoluted as SwallowedExceptionListener
792                        // uses Exception rather than Throwable
793                        PoolUtils.checkRethrow(t);
794                        swallowException(new Exception(t));
795                        // Don't evict on error conditions
796                        evict = false;
797                    }
798
799                    if (evict) {
800                        destroy(underTest);
801                        destroyedByEvictorCount.incrementAndGet();
802                    } else {
803                        if (testWhileIdle) {
804                            boolean active = false;
805                            try {
806                                factory.activateObject(underTest);
807                                active = true;
808                            } catch (Exception e) {
809                                destroy(underTest);
810                                destroyedByEvictorCount.incrementAndGet();
811                            }
812                            if (active) {
813                                if (!factory.validateObject(underTest)) {
814                                    destroy(underTest);
815                                    destroyedByEvictorCount.incrementAndGet();
816                                } else {
817                                    try {
818                                        factory.passivateObject(underTest);
819                                    } catch (Exception e) {
820                                        destroy(underTest);
821                                        destroyedByEvictorCount.incrementAndGet();
822                                    }
823                                }
824                            }
825                        }
826                        if (!underTest.endEvictionTest(idleObjects)) {
827                            // TODO - May need to add code here once additional
828                            // states are used
829                        }
830                    }
831                }
832            }
833        }
834        AbandonedConfig ac = this.abandonedConfig;
835        if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
836            removeAbandoned(ac);
837        }
838    }
839
840    /**
841     * Attempts to create a new wrapped pooled object.
842     * <p>
843     * If there are {@link #getMaxTotal()} objects already in circulation
844     * or in process of being created, this method returns null.
845     *
846     * @return The new wrapped pooled object
847     *
848     * @throws Exception if the object factory's {@code makeObject} fails
849     */
850    private PooledObject<T> create() throws Exception {
851        int localMaxTotal = getMaxTotal();
852        long newCreateCount = createCount.incrementAndGet();
853        if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
854                newCreateCount > Integer.MAX_VALUE) {
855            createCount.decrementAndGet();
856            return null;
857        }
858
859        final PooledObject<T> p;
860        try {
861            p = factory.makeObject();
862        } catch (Exception e) {
863            createCount.decrementAndGet();
864            throw e;
865        }
866
867        AbandonedConfig ac = this.abandonedConfig;
868        if (ac != null && ac.getLogAbandoned()) {
869            p.setLogAbandoned(true);
870        }
871
872        createdCount.incrementAndGet();
873        allObjects.put(p.getObject(), p);
874        return p;
875    }
876
877    /**
878     * Destroys a wrapped pooled object.
879     *
880     * @param toDestory The wrapped pooled object to destroy
881     *
882     * @throws Exception If the factory fails to destroy the pooled object
883     *                   cleanly
884     */
885    private void destroy(PooledObject<T> toDestory) throws Exception {
886        toDestory.invalidate();
887        idleObjects.remove(toDestory);
888        allObjects.remove(toDestory.getObject());
889        try {
890            factory.destroyObject(toDestory);
891        } finally {
892            destroyedCount.incrementAndGet();
893            createCount.decrementAndGet();
894        }
895    }
896
897    @Override
898    void ensureMinIdle() throws Exception {
899        ensureIdle(getMinIdle(), true);
900    }
901
902    /**
903     * Tries to ensure that {@code idleCount} idle instances exist in the pool.
904     * <p>
905     * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
906     * or the total number of objects (idle, checked out, or being created) reaches
907     * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
908     * there are threads waiting to check out instances from the pool.
909     *
910     * @param idleCount the number of idle instances desired
911     * @param always true means create instances even if the pool has no threads waiting
912     * @throws Exception if the factory's makeObject throws
913     */
914    private void ensureIdle(int idleCount, boolean always) throws Exception {
915        if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
916            return;
917        }
918
919        while (idleObjects.size() < idleCount) {
920            PooledObject<T> p = create();
921            if (p == null) {
922                // Can't create objects, no reason to think another call to
923                // create will work. Give up.
924                break;
925            }
926            if (getLifo()) {
927                idleObjects.addFirst(p);
928            } else {
929                idleObjects.addLast(p);
930            }
931        }
932        if (isClosed()) {
933            // Pool closed while object was being added to idle objects.
934            // Make sure the returned object is destroyed rather than left
935            // in the idle object pool (which would effectively be a leak)
936            clear();
937        }
938    }
939
940    /**
941     * Create an object, and place it into the pool. addObject() is useful for
942     * "pre-loading" a pool with idle objects.
943     */
944    @Override
945    public void addObject() throws Exception {
946        assertOpen();
947        if (factory == null) {
948            throw new IllegalStateException(
949                    "Cannot add objects without a factory.");
950        }
951        PooledObject<T> p = create();
952        addIdleObject(p);
953    }
954
955    /**
956     * Add the provided wrapped pooled object to the set of idle objects for
957     * this pool. The object must already be part of the pool.
958     *
959     * @param p The object to make idle
960     *
961     * @throws Exception If the factory fails to passivate the object
962     */
963    private void addIdleObject(PooledObject<T> p) throws Exception {
964        if (p != null) {
965            factory.passivateObject(p);
966            if (getLifo()) {
967                idleObjects.addFirst(p);
968            } else {
969                idleObjects.addLast(p);
970            }
971        }
972    }
973
974    /**
975     * Calculate the number of objects to test in a run of the idle object
976     * evictor.
977     *
978     * @return The number of objects to test for validity
979     */
980    private int getNumTests() {
981        int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
982        if (numTestsPerEvictionRun >= 0) {
983            return Math.min(numTestsPerEvictionRun, idleObjects.size());
984        } else {
985            return (int) (Math.ceil(idleObjects.size() /
986                    Math.abs((double) numTestsPerEvictionRun)));
987        }
988    }
989
990    /**
991     * Recover abandoned objects which have been checked out but
992     * not used since longer than the removeAbandonedTimeout.
993     *
994     * @param ac The configuration to use to identify abandoned objects
995     */
996    private void removeAbandoned(AbandonedConfig ac) {
997        // Generate a list of abandoned objects to remove
998        final long now = System.currentTimeMillis();
999        final long timeout =
1000                now - (ac.getRemoveAbandonedTimeout() * 1000L);
1001        ArrayList<PooledObject<T>> remove = new ArrayList<PooledObject<T>>();
1002        Iterator<PooledObject<T>> it = allObjects.values().iterator();
1003        while (it.hasNext()) {
1004            PooledObject<T> pooledObject = it.next();
1005            synchronized (pooledObject) {
1006                if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
1007                        pooledObject.getLastUsedTime() <= timeout) {
1008                    pooledObject.markAbandoned();
1009                    remove.add(pooledObject);
1010                }
1011            }
1012        }
1013
1014        // Now remove the abandoned objects
1015        Iterator<PooledObject<T>> itr = remove.iterator();
1016        while (itr.hasNext()) {
1017            PooledObject<T> pooledObject = itr.next();
1018            if (ac.getLogAbandoned()) {
1019                pooledObject.printStackTrace(ac.getLogWriter());
1020            }
1021            try {
1022                invalidateObject(pooledObject.getObject());
1023            } catch (Exception e) {
1024                e.printStackTrace();
1025            }
1026        }
1027    }
1028
1029
1030    //--- Usage tracking support -----------------------------------------------
1031
1032    @Override
1033    public void use(T pooledObject) {
1034        AbandonedConfig ac = this.abandonedConfig;
1035        if (ac != null && ac.getUseUsageTracking()) {
1036            PooledObject<T> wrapper = allObjects.get(pooledObject);
1037            wrapper.use();
1038        }
1039    }
1040
1041
1042    //--- JMX support ----------------------------------------------------------
1043
1044    private volatile String factoryType = null;
1045
1046    /**
1047     * Return an estimate of the number of threads currently blocked waiting for
1048     * an object from the pool. This is intended for monitoring only, not for
1049     * synchronization control.
1050     *
1051     * @return The estimate of the number of threads currently blocked waiting
1052     *         for an object from the pool
1053     */
1054    @Override
1055    public int getNumWaiters() {
1056        if (getBlockWhenExhausted()) {
1057            return idleObjects.getTakeQueueLength();
1058        } else {
1059            return 0;
1060        }
1061    }
1062
1063    /**
1064     * Return the type - including the specific type rather than the generic -
1065     * of the factory.
1066     *
1067     * @return A string representation of the factory type
1068     */
1069    @Override
1070    public String getFactoryType() {
1071        // Not thread safe. Accept that there may be multiple evaluations.
1072        if (factoryType == null) {
1073            StringBuilder result = new StringBuilder();
1074            result.append(factory.getClass().getName());
1075            result.append('<');
1076            Class<?> pooledObjectType =
1077                    PoolImplUtils.getFactoryType(factory.getClass());
1078            result.append(pooledObjectType.getName());
1079            result.append('>');
1080            factoryType = result.toString();
1081        }
1082        return factoryType;
1083    }
1084
1085    /**
1086     * Provides information on all the objects in the pool, both idle (waiting
1087     * to be borrowed) and active (currently borrowed).
1088     * <p>
1089     * Note: This is named listAllObjects so it is presented as an operation via
1090     * JMX. That means it won't be invoked unless the explicitly requested
1091     * whereas all attributes will be automatically requested when viewing the
1092     * attributes for an object in a tool like JConsole.
1093     *
1094     * @return Information grouped on all the objects in the pool
1095     */
1096    @Override
1097    public Set<DefaultPooledObjectInfo> listAllObjects() {
1098        Set<DefaultPooledObjectInfo> result =
1099                new HashSet<DefaultPooledObjectInfo>(allObjects.size());
1100        for (PooledObject<T> p : allObjects.values()) {
1101            result.add(new DefaultPooledObjectInfo(p));
1102        }
1103        return result;
1104    }
1105
1106    // --- configuration attributes --------------------------------------------
1107
1108    private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
1109    private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
1110    private final PooledObjectFactory<T> factory;
1111
1112
1113    // --- internal attributes -------------------------------------------------
1114
1115    /*
1116     * All of the objects currently associated with this pool in any state. It
1117     * excludes objects that have been destroyed. The size of
1118     * {@link #allObjects} will always be less than or equal to {@link
1119     * #_maxActive}. Map keys are pooled objects, values are the PooledObject
1120     * wrappers used internally by the pool.
1121     */
1122    private final Map<T, PooledObject<T>> allObjects =
1123        new ConcurrentHashMap<T, PooledObject<T>>();
1124    /*
1125     * The combined count of the currently created objects and those in the
1126     * process of being created. Under load, it may exceed {@link #_maxActive}
1127     * if multiple threads try and create a new object at the same time but
1128     * {@link #create()} will ensure that there are never more than
1129     * {@link #_maxActive} objects created at any one time.
1130     */
1131    private final AtomicLong createCount = new AtomicLong(0);
1132    private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
1133
1134    // JMX specific attributes
1135    private static final String ONAME_BASE =
1136        "org.apache.commons.pool2:type=GenericObjectPool,name=";
1137
1138    // Additional configuration properties for abandoned object tracking
1139    private volatile AbandonedConfig abandonedConfig = null;
1140}