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.io.PrintWriter;
020import java.io.StringWriter;
021import java.io.Writer;
022import java.lang.management.ManagementFactory;
023import java.lang.ref.WeakReference;
024import java.lang.reflect.InvocationTargetException;
025import java.time.Duration;
026import java.util.Arrays;
027import java.util.Deque;
028import java.util.Iterator;
029import java.util.TimerTask;
030import java.util.concurrent.ScheduledFuture;
031import java.util.concurrent.atomic.AtomicLong;
032
033import javax.management.InstanceAlreadyExistsException;
034import javax.management.InstanceNotFoundException;
035import javax.management.MBeanRegistrationException;
036import javax.management.MBeanServer;
037import javax.management.MalformedObjectNameException;
038import javax.management.NotCompliantMBeanException;
039import javax.management.ObjectName;
040
041import org.apache.commons.pool2.BaseObject;
042import org.apache.commons.pool2.PooledObject;
043import org.apache.commons.pool2.PooledObjectState;
044import org.apache.commons.pool2.SwallowedExceptionListener;
045
046/**
047 * Base class that provides common functionality for {@link GenericObjectPool}
048 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
049 * reduce code duplication between the two pool implementations.
050 *
051 * @param <T> Type of element pooled in this pool.
052 *
053 * This class is intended to be thread-safe.
054 *
055 * @since 2.0
056 */
057public abstract class BaseGenericObjectPool<T> extends BaseObject {
058
059    /**
060     * The idle object eviction iterator. Holds a reference to the idle objects.
061     */
062    class EvictionIterator implements Iterator<PooledObject<T>> {
063
064        private final Deque<PooledObject<T>> idleObjects;
065        private final Iterator<PooledObject<T>> idleObjectIterator;
066
067        /**
068         * Create an EvictionIterator for the provided idle instance deque.
069         * @param idleObjects underlying deque
070         */
071        EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
072            this.idleObjects = idleObjects;
073
074            if (getLifo()) {
075                idleObjectIterator = idleObjects.descendingIterator();
076            } else {
077                idleObjectIterator = idleObjects.iterator();
078            }
079        }
080
081        /**
082         * Gets the idle object deque referenced by this iterator.
083         * @return the idle object deque
084         */
085        public Deque<PooledObject<T>> getIdleObjects() {
086            return idleObjects;
087        }
088
089        /** {@inheritDoc} */
090        @Override
091        public boolean hasNext() {
092            return idleObjectIterator.hasNext();
093        }
094
095        /** {@inheritDoc} */
096        @Override
097        public PooledObject<T> next() {
098            return idleObjectIterator.next();
099        }
100
101        /** {@inheritDoc} */
102        @Override
103        public void remove() {
104            idleObjectIterator.remove();
105        }
106
107    }
108
109    /**
110     * The idle object evictor {@link TimerTask}.
111     *
112     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
113     */
114    class Evictor implements Runnable {
115
116        private ScheduledFuture<?> scheduledFuture;
117
118        /**
119         * Cancels the scheduled future.
120         */
121        void cancel() {
122            scheduledFuture.cancel(false);
123        }
124
125
126        /**
127         * Run pool maintenance.  Evict objects qualifying for eviction and then
128         * ensure that the minimum number of idle instances are available.
129         * Since the Timer that invokes Evictors is shared for all Pools but
130         * pools may exist in different class loaders, the Evictor ensures that
131         * any actions taken are under the class loader of the factory
132         * associated with the pool.
133         */
134        @Override
135        public void run() {
136            final ClassLoader savedClassLoader =
137                    Thread.currentThread().getContextClassLoader();
138            try {
139                if (factoryClassLoader != null) {
140                    // Set the class loader for the factory
141                    final ClassLoader cl = factoryClassLoader.get();
142                    if (cl == null) {
143                        // The pool has been dereferenced and the class loader
144                        // GC'd. Cancel this timer so the pool can be GC'd as
145                        // well.
146                        cancel();
147                        return;
148                    }
149                    Thread.currentThread().setContextClassLoader(cl);
150                }
151
152                // Evict from the pool
153                try {
154                    evict();
155                } catch(final Exception e) {
156                    swallowException(e);
157                } catch(final OutOfMemoryError oome) {
158                    // Log problem but give evictor thread a chance to continue
159                    // in case error is recoverable
160                    oome.printStackTrace(System.err);
161                }
162                // Re-create idle instances.
163                try {
164                    ensureMinIdle();
165                } catch (final Exception e) {
166                    swallowException(e);
167                }
168            } finally {
169                // Restore the previous CCL
170                Thread.currentThread().setContextClassLoader(savedClassLoader);
171            }
172        }
173
174
175        /**
176         * Sets the scheduled future.
177         *
178         * @param scheduledFuture the scheduled future.
179         */
180        void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
181            this.scheduledFuture = scheduledFuture;
182        }
183
184    }
185
186    /**
187     * Wrapper for objects under management by the pool.
188     *
189     * GenericObjectPool and GenericKeyedObjectPool maintain references to all
190     * objects under management using maps keyed on the objects. This wrapper
191     * class ensures that objects can work as hash keys.
192     *
193     * @param <T> type of objects in the pool
194     */
195    static class IdentityWrapper<T> {
196        /** Wrapped object */
197        private final T instance;
198
199        /**
200         * Create a wrapper for an instance.
201         *
202         * @param instance object to wrap
203         */
204        public IdentityWrapper(final T instance) {
205            this.instance = instance;
206        }
207
208        @Override
209        @SuppressWarnings("rawtypes")
210        public boolean equals(final Object other) {
211            return  other instanceof IdentityWrapper &&
212                    ((IdentityWrapper) other).instance == instance;
213        }
214
215        /**
216         * @return the wrapped object
217         */
218        public T getObject() {
219            return instance;
220        }
221
222        @Override
223        public int hashCode() {
224            return System.identityHashCode(instance);
225        }
226
227        @Override
228        public String toString() {
229            final StringBuilder builder = new StringBuilder();
230            builder.append("IdentityWrapper [instance=");
231            builder.append(instance);
232            builder.append("]");
233            return builder.toString();
234        }
235    }
236    /**
237     * Maintains a cache of values for a single metric and reports
238     * statistics on the cached values.
239     */
240    private class StatsStore {
241
242        private final AtomicLong[] values;
243        private final int size;
244        private int index;
245
246        /**
247         * Create a StatsStore with the given cache size.
248         *
249         * @param size number of values to maintain in the cache.
250         */
251        StatsStore(final int size) {
252            this.size = size;
253            values = new AtomicLong[size];
254            for (int i = 0; i < size; i++) {
255                values[i] = new AtomicLong(-1);
256            }
257        }
258
259        void add(final Duration value) {
260            add(value.toMillis());
261        }
262
263        /**
264         * Adds a value to the cache.  If the cache is full, one of the
265         * existing values is replaced by the new value.
266         *
267         * @param value new value to add to the cache.
268         */
269        synchronized void add(final long value) {
270            values[index].set(value);
271            index++;
272            if (index == size) {
273                index = 0;
274            }
275        }
276
277        /**
278         * Gets the mean of the cached values.
279         *
280         * @return the mean of the cache, truncated to long
281         */
282        public long getMean() {
283            double result = 0;
284            int counter = 0;
285            for (int i = 0; i < size; i++) {
286                final long value = values[i].get();
287                if (value != -1) {
288                    counter++;
289                    result = result * ((counter - 1) / (double) counter) +
290                            value/(double) counter;
291                }
292            }
293            return (long) result;
294        }
295
296        @Override
297        public String toString() {
298            final StringBuilder builder = new StringBuilder();
299            builder.append("StatsStore [values=");
300            builder.append(Arrays.toString(values));
301            builder.append(", size=");
302            builder.append(size);
303            builder.append(", index=");
304            builder.append(index);
305            builder.append("]");
306            return builder.toString();
307        }
308    }
309    // Constants
310    /**
311     * The size of the caches used to store historical data for some attributes
312     * so that rolling means may be calculated.
313     */
314    public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
315    private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
316    // Configuration attributes
317    private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
318    private volatile boolean blockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
319    private volatile Duration maxWait = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
320    private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
321    private final boolean fairness;
322    private volatile boolean testOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
323    private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
324    private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
325    private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
326    private volatile Duration timeBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS;
327    private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
328
329    private volatile Duration minEvictableIdleTime = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME;
330    private volatile Duration softMinEvictableIdleTime = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME;
331    private volatile EvictionPolicy<T> evictionPolicy;
332    private volatile Duration evictorShutdownTimeout = BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT;
333    // Internal (primarily state) attributes
334    final Object closeLock = new Object();
335    volatile boolean closed;
336
337
338    final Object evictionLock = new Object();
339    private Evictor evictor = null; // @GuardedBy("evictionLock")
340    EvictionIterator evictionIterator = null; // @GuardedBy("evictionLock")
341    /*
342     * Class loader for evictor thread to use since, in a JavaEE or similar
343     * environment, the context class loader for the evictor thread may not have
344     * visibility of the correct factory. See POOL-161. Uses a weak reference to
345     * avoid potential memory leaks if the Pool is discarded rather than closed.
346     */
347    private final WeakReference<ClassLoader> factoryClassLoader;
348    // Monitoring (primarily JMX) attributes
349    private final ObjectName objectName;
350    private final String creationStackTrace;
351    private final AtomicLong borrowedCount = new AtomicLong(0);
352    private final AtomicLong returnedCount = new AtomicLong(0);
353    final AtomicLong createdCount = new AtomicLong(0);
354    final AtomicLong destroyedCount = new AtomicLong(0);
355    final AtomicLong destroyedByEvictorCount = new AtomicLong(0);
356    final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
357    private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
358
359
360    private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
361
362
363    private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
364
365    private final AtomicLong maxBorrowWaitTimeMillis = new AtomicLong(0L);
366
367    private volatile SwallowedExceptionListener swallowedExceptionListener = null;
368
369    /**
370     * Handles JMX registration (if required) and the initialization required for
371     * monitoring.
372     *
373     * @param config        Pool configuration
374     * @param jmxNameBase   The default base JMX name for the new pool unless
375     *                      overridden by the config
376     * @param jmxNamePrefix Prefix to be used for JMX name for the new pool
377     */
378    public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config,
379            final String jmxNameBase, final String jmxNamePrefix) {
380        if (config.getJmxEnabled()) {
381            this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix);
382        } else {
383            this.objectName = null;
384        }
385
386        // Populate the creation stack trace
387        this.creationStackTrace = getStackTrace(new Exception());
388
389        // save the current TCCL (if any) to be used later by the evictor Thread
390        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
391        if (cl == null) {
392            factoryClassLoader = null;
393        } else {
394            factoryClassLoader = new WeakReference<>(cl);
395        }
396
397        fairness = config.getFairness();
398    }
399
400    /**
401     * Verifies that the pool is open.
402     * @throws IllegalStateException if the pool is closed.
403     */
404    final void assertOpen() throws IllegalStateException {
405        if (isClosed()) {
406            throw new IllegalStateException("Pool not open");
407        }
408    }
409
410    /**
411     * Closes the pool, destroys the remaining idle objects and, if registered
412     * in JMX, deregisters it.
413     */
414    public abstract void close();
415
416    /**
417     * Tries to ensure that the configured minimum number of idle instances are
418     * available in the pool.
419     * @throws Exception if an error occurs creating idle instances
420     */
421    abstract void ensureMinIdle() throws Exception;
422
423    /**
424     * <p>Perform {@code numTests} idle object eviction tests, evicting
425     * examined objects that meet the criteria for eviction. If
426     * {@code testWhileIdle} is true, examined objects are validated
427     * when visited (and removed if invalid); otherwise only objects that
428     * have been idle for more than {@code minEvicableIdleTimeMillis}
429     * are removed.</p>
430     *
431     * @throws Exception when there is a problem evicting idle objects.
432     */
433    public abstract void evict() throws Exception;
434
435    /**
436     * Gets whether to block when the {@code borrowObject()} method is
437     * invoked when the pool is exhausted (the maximum number of "active"
438     * objects has been reached).
439     *
440     * @return {@code true} if {@code borrowObject()} should block
441     *         when the pool is exhausted
442     *
443     * @see #setBlockWhenExhausted
444     */
445    public final boolean getBlockWhenExhausted() {
446        return blockWhenExhausted;
447    }
448
449    /**
450     * The total number of objects successfully borrowed from this pool over the
451     * lifetime of the pool.
452     * @return the borrowed object count
453     */
454    public final long getBorrowedCount() {
455        return borrowedCount.get();
456    }
457
458    /**
459     * The total number of objects created for this pool over the lifetime of
460     * the pool.
461     * @return the created object count
462     */
463    public final long getCreatedCount() {
464        return createdCount.get();
465    }
466
467    /**
468     * Provides the stack trace for the call that created this pool. JMX
469     * registration may trigger a memory leak so it is important that pools are
470     * deregistered when no longer used by calling the {@link #close()} method.
471     * This method is provided to assist with identifying code that creates but
472     * does not close it thereby creating a memory leak.
473     * @return pool creation stack trace
474     */
475    public final String getCreationStackTrace() {
476        return creationStackTrace;
477    }
478
479    /**
480     * The total number of objects destroyed by this pool as a result of failing
481     * validation during {@code borrowObject()} over the lifetime of the
482     * pool.
483     * @return validation destroyed object count
484     */
485    public final long getDestroyedByBorrowValidationCount() {
486        return destroyedByBorrowValidationCount.get();
487    }
488
489    /**
490     * The total number of objects destroyed by the evictor associated with this
491     * pool over the lifetime of the pool.
492     * @return the evictor destroyed object count
493     */
494    public final long getDestroyedByEvictorCount() {
495        return destroyedByEvictorCount.get();
496    }
497
498    /**
499     * The total number of objects destroyed by this pool over the lifetime of
500     * the pool.
501     * @return the destroyed object count
502     */
503    public final long getDestroyedCount() {
504        return destroyedCount.get();
505    }
506
507    /**
508     * Gets the {@link EvictionPolicy} defined for this pool.
509     *
510     * @return the eviction policy
511     * @since 2.4
512     * @since 2.6.0 Changed access from protected to public.
513     */
514    public EvictionPolicy<T> getEvictionPolicy() {
515        return evictionPolicy;
516    }
517
518    /**
519     * Gets the name of the {@link EvictionPolicy} implementation that is
520     * used by this pool.
521     *
522     * @return  The fully qualified class name of the {@link EvictionPolicy}
523     *
524     * @see #setEvictionPolicyClassName(String)
525     */
526    public final String getEvictionPolicyClassName() {
527        return evictionPolicy.getClass().getName();
528    }
529
530    /**
531     * Gets the timeout that will be used when waiting for the Evictor to
532     * shutdown if this pool is closed and it is the only pool still using the
533     * the value for the Evictor.
534     *
535     * @return  The timeout that will be used while waiting for
536     *          the Evictor to shut down.
537     * @since 2.10.0
538     */
539    public final Duration getEvictorShutdownTimeout() {
540        return evictorShutdownTimeout;
541    }
542
543    /**
544     * Gets the timeout that will be used when waiting for the Evictor to
545     * shutdown if this pool is closed and it is the only pool still using the
546     * the value for the Evictor.
547     *
548     * @return  The timeout in milliseconds that will be used while waiting for
549     *          the Evictor to shut down.
550     * @deprecated Use {@link #getEvictorShutdownTimeout()}.
551     */
552    @Deprecated
553    public final long getEvictorShutdownTimeoutMillis() {
554        return evictorShutdownTimeout.toMillis();
555    }
556
557    /**
558     * Gets whether or not the pool serves threads waiting to borrow objects fairly.
559     * True means that waiting threads are served as if waiting in a FIFO queue.
560     *
561     * @return {@code true} if waiting threads are to be served
562     *             by the pool in arrival order
563     */
564    public final boolean getFairness() {
565        return fairness;
566    }
567
568    /**
569     * Provides the name under which the pool has been registered with the
570     * platform MBean server or {@code null} if the pool has not been
571     * registered.
572     * @return the JMX name
573     */
574    public final ObjectName getJmxName() {
575        return objectName;
576    }
577
578    /**
579     * Gets whether the pool has LIFO (last in, first out) behavior with
580     * respect to idle objects - always returning the most recently used object
581     * from the pool, or as a FIFO (first in, first out) queue, where the pool
582     * always returns the oldest object in the idle object pool.
583     *
584     * @return {@code true} if the pool is configured with LIFO behavior
585     *         or {@code false} if the pool is configured with FIFO
586     *         behavior
587     *
588     * @see #setLifo
589     */
590    public final boolean getLifo() {
591        return lifo;
592    }
593
594    /**
595     * The maximum time a thread has waited to borrow objects from the pool.
596     * @return maximum wait time in milliseconds since the pool was created
597     */
598    public final long getMaxBorrowWaitTimeMillis() {
599        return maxBorrowWaitTimeMillis.get();
600    }
601
602    /**
603     * Gets the maximum number of objects that can be allocated by the pool
604     * (checked out to clients, or idle awaiting checkout) at a given time. When
605     * negative, there is no limit to the number of objects that can be
606     * managed by the pool at one time.
607     *
608     * @return the cap on the total number of object instances managed by the
609     *         pool.
610     *
611     * @see #setMaxTotal
612     */
613    public final int getMaxTotal() {
614        return maxTotal;
615    }
616
617    /**
618     * Gets the maximum amount of time (in milliseconds) the
619     * {@code borrowObject()} method should block before throwing an
620     * exception when the pool is exhausted and
621     * {@link #getBlockWhenExhausted} is true. When less than 0, the
622     * {@code borrowObject()} method may block indefinitely.
623     *
624     * @return the maximum number of milliseconds {@code borrowObject()}
625     *         will block.
626     *
627     * @see #setMaxWaitMillis
628     * @see #setBlockWhenExhausted
629     */
630    public final long getMaxWaitMillis() {
631        return maxWait.toMillis();
632    }
633
634    /**
635     * The mean time objects are active for based on the last {@link
636     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
637     * @return mean time an object has been checked out from the pool among
638     * recently returned objects
639     */
640    public final long getMeanActiveTimeMillis() {
641        return activeTimes.getMean();
642    }
643
644    /**
645     * The mean time threads wait to borrow an object based on the last {@link
646     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
647     * @return mean time in milliseconds that a recently served thread has had
648     * to wait to borrow an object from the pool
649     */
650    public final long getMeanBorrowWaitTimeMillis() {
651        return waitTimes.getMean();
652    }
653
654    /**
655     * The mean time objects are idle for based on the last {@link
656     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
657     * @return mean time an object has been idle in the pool among recently
658     * borrowed objects
659     */
660    public final long getMeanIdleTimeMillis() {
661        return idleTimes.getMean();
662    }
663
664    /**
665     * Gets the minimum amount of time an object may sit idle in the pool
666     * before it is eligible for eviction by the idle object evictor (if any -
667     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
668     * no objects will be evicted from the pool due to idle time alone.
669     *
670     * @return minimum amount of time an object may sit idle in the pool before
671     *         it is eligible for eviction
672     *
673     * @see #setMinEvictableIdleTimeMillis
674     * @see #setTimeBetweenEvictionRunsMillis
675     * @since 2.10.0
676     */
677    public final Duration getMinEvictableIdleTime() {
678        return minEvictableIdleTime;
679    }
680
681    /**
682     * Gets the minimum amount of time an object may sit idle in the pool
683     * before it is eligible for eviction by the idle object evictor (if any -
684     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
685     * no objects will be evicted from the pool due to idle time alone.
686     *
687     * @return minimum amount of time an object may sit idle in the pool before
688     *         it is eligible for eviction
689     *
690     * @see #setMinEvictableIdleTimeMillis
691     * @see #setTimeBetweenEvictionRunsMillis
692     * @deprecated Use {@link #getMinEvictableIdleTime()}.
693     */
694    @Deprecated
695    public final long getMinEvictableIdleTimeMillis() {
696        return minEvictableIdleTime.toMillis();
697    }
698
699    /**
700     * The number of instances currently idle in this pool.
701     * @return count of instances available for checkout from the pool
702     */
703    public abstract int getNumIdle();
704
705    /**
706     * Gets the maximum number of objects to examine during each run (if any)
707     * of the idle object evictor thread. When positive, the number of tests
708     * performed for a run will be the minimum of the configured value and the
709     * number of idle instances in the pool. When negative, the number of tests
710     * performed will be <code>ceil({@link #getNumIdle}/
711     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
712     * value is {@code -n} roughly one nth of the idle objects will be
713     * tested per run.
714     *
715     * @return max number of objects to examine during each evictor run
716     *
717     * @see #setNumTestsPerEvictionRun
718     * @see #setTimeBetweenEvictionRunsMillis
719     */
720    public final int getNumTestsPerEvictionRun() {
721        return numTestsPerEvictionRun;
722    }
723
724    /**
725     * The total number of objects returned to this pool over the lifetime of
726     * the pool. This excludes attempts to return the same object multiple
727     * times.
728     * @return the returned object count
729     */
730    public final long getReturnedCount() {
731        return returnedCount.get();
732    }
733
734    /**
735     * Gets the minimum amount of time an object may sit idle in the pool
736     * before it is eligible for eviction by the idle object evictor (if any -
737     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
738     * with the extra condition that at least {@code minIdle} object
739     * instances remain in the pool. This setting is overridden by
740     * {@link #getMinEvictableIdleTime} (that is, if
741     * {@link #getMinEvictableIdleTime} is positive, then
742     * {@link #getSoftMinEvictableIdleTime} is ignored).
743     *
744     * @return minimum amount of time an object may sit idle in the pool before
745     *         it is eligible for eviction if minIdle instances are available
746     *
747     * @see #setSoftMinEvictableIdleTime(Duration)
748     * @since 2.10.0
749     */
750    public final Duration getSoftMinEvictableIdleTime() {
751        return softMinEvictableIdleTime;
752    }
753
754    /**
755     * Gets the minimum amount of time an object may sit idle in the pool
756     * before it is eligible for eviction by the idle object evictor (if any -
757     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
758     * with the extra condition that at least {@code minIdle} object
759     * instances remain in the pool. This setting is overridden by
760     * {@link #getMinEvictableIdleTimeMillis} (that is, if
761     * {@link #getMinEvictableIdleTimeMillis} is positive, then
762     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
763     *
764     * @return minimum amount of time an object may sit idle in the pool before
765     *         it is eligible for eviction if minIdle instances are available
766     *
767     * @see #setSoftMinEvictableIdleTimeMillis
768     * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
769     */
770    @Deprecated
771    public final long getSoftMinEvictableIdleTimeMillis() {
772        return softMinEvictableIdleTime.toMillis();
773    }
774
775    /**
776     * Gets the stack trace of an exception as a string.
777     * @param e exception to trace
778     * @return exception stack trace as a string
779     */
780    private String getStackTrace(final Exception e) {
781        // Need the exception in string form to prevent the retention of
782        // references to classes in the stack trace that could trigger a memory
783        // leak in a container environment.
784        final Writer w = new StringWriter();
785        final PrintWriter pw = new PrintWriter(w);
786        e.printStackTrace(pw);
787        return w.toString();
788    }
789
790    /**
791     * The listener used (if any) to receive notifications of exceptions
792     * unavoidably swallowed by the pool.
793     *
794     * @return The listener or {@code null} for no listener
795     */
796    public final SwallowedExceptionListener getSwallowedExceptionListener() {
797        return swallowedExceptionListener;
798    }
799
800    /**
801     * Gets whether objects borrowed from the pool will be validated before
802     * being returned from the {@code borrowObject()} method. Validation is
803     * performed by the {@code validateObject()} method of the factory
804     * associated with the pool. If the object fails to validate, it will be
805     * removed from the pool and destroyed, and a new attempt will be made to
806     * borrow an object from the pool.
807     *
808     * @return {@code true} if objects are validated before being returned
809     *         from the {@code borrowObject()} method
810     *
811     * @see #setTestOnBorrow
812     */
813    public final boolean getTestOnBorrow() {
814        return testOnBorrow;
815    }
816
817    /**
818     * Gets whether objects created for the pool will be validated before
819     * being returned from the {@code borrowObject()} method. Validation is
820     * performed by the {@code validateObject()} method of the factory
821     * associated with the pool. If the object fails to validate, then
822     * {@code borrowObject()} will fail.
823     *
824     * @return {@code true} if newly created objects are validated before
825     *         being returned from the {@code borrowObject()} method
826     *
827     * @see #setTestOnCreate
828     *
829     * @since 2.2
830     */
831    public final boolean getTestOnCreate() {
832        return testOnCreate;
833    }
834
835    /**
836     * Gets whether objects borrowed from the pool will be validated when
837     * they are returned to the pool via the {@code returnObject()} method.
838     * Validation is performed by the {@code validateObject()} method of
839     * the factory associated with the pool. Returning objects that fail validation
840     * are destroyed rather then being returned the pool.
841     *
842     * @return {@code true} if objects are validated on return to
843     *         the pool via the {@code returnObject()} method
844     *
845     * @see #setTestOnReturn
846     */
847    public final boolean getTestOnReturn() {
848        return testOnReturn;
849    }
850
851    /**
852     * Gets whether objects sitting idle in the pool will be validated by the
853     * idle object evictor (if any - see
854     * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
855     * by the {@code validateObject()} method of the factory associated
856     * with the pool. If the object fails to validate, it will be removed from
857     * the pool and destroyed.
858     *
859     * @return {@code true} if objects will be validated by the evictor
860     *
861     * @see #setTestWhileIdle
862     * @see #setTimeBetweenEvictionRunsMillis
863     */
864    public final boolean getTestWhileIdle() {
865        return testWhileIdle;
866    }
867
868    /**
869     * Gets the duration to sleep between runs of the idle
870     * object evictor thread. When non-positive, no idle object evictor thread
871     * will be run.
872     *
873     * @return number of milliseconds to sleep between evictor runs
874     *
875     * @see #setTimeBetweenEvictionRuns
876     * @since 2.10.0
877     */
878    public final Duration getTimeBetweenEvictionRuns() {
879        return timeBetweenEvictionRuns;
880    }
881
882    /**
883     * Gets the number of milliseconds to sleep between runs of the idle
884     * object evictor thread. When non-positive, no idle object evictor thread
885     * will be run.
886     *
887     * @return number of milliseconds to sleep between evictor runs
888     *
889     * @see #setTimeBetweenEvictionRunsMillis
890     * @deprecated Use {@link #getTimeBetweenEvictionRuns()}.
891     */
892    @Deprecated
893    public final long getTimeBetweenEvictionRunsMillis() {
894        return timeBetweenEvictionRuns.toMillis();
895    }
896
897    /**
898     * Has this pool instance been closed.
899     * @return {@code true} when this pool has been closed.
900     */
901    public final boolean isClosed() {
902        return closed;
903    }
904
905    /**
906     * Registers the pool with the platform MBean server.
907     * The registered name will be
908     * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
909     * integer greater than or equal to 1 such that the name is not already
910     * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
911     * returning null.
912     *
913     * @param config Pool configuration
914     * @param jmxNameBase default base JMX name for this pool
915     * @param jmxNamePrefix name prefix
916     * @return registered ObjectName, null if registration fails
917     */
918    private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
919            final String jmxNameBase, String jmxNamePrefix) {
920        ObjectName newObjectName = null;
921        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
922        int i = 1;
923        boolean registered = false;
924        String base = config.getJmxNameBase();
925        if (base == null) {
926            base = jmxNameBase;
927        }
928        while (!registered) {
929            try {
930                ObjectName objName;
931                // Skip the numeric suffix for the first pool in case there is
932                // only one so the names are cleaner.
933                if (i == 1) {
934                    objName = new ObjectName(base + jmxNamePrefix);
935                } else {
936                    objName = new ObjectName(base + jmxNamePrefix + i);
937                }
938                mbs.registerMBean(this, objName);
939                newObjectName = objName;
940                registered = true;
941            } catch (final MalformedObjectNameException e) {
942                if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
943                        jmxNamePrefix) && jmxNameBase.equals(base)) {
944                    // Shouldn't happen. Skip registration if it does.
945                    registered = true;
946                } else {
947                    // Must be an invalid name. Use the defaults instead.
948                    jmxNamePrefix =
949                            BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
950                    base = jmxNameBase;
951                }
952            } catch (final InstanceAlreadyExistsException e) {
953                // Increment the index and try again
954                i++;
955            } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
956                // Shouldn't happen. Skip registration if it does.
957                registered = true;
958            }
959        }
960        return newObjectName;
961    }
962
963    /**
964     * Unregisters this pool's MBean.
965     */
966    final void jmxUnregister() {
967        if (objectName != null) {
968            try {
969                ManagementFactory.getPlatformMBeanServer().unregisterMBean(
970                        objectName);
971            } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
972                swallowException(e);
973            }
974        }
975    }
976
977    /**
978     * Marks the object as returning to the pool.
979     * @param pooledObject instance to return to the keyed pool
980     */
981    protected void markReturningState(final PooledObject<T> pooledObject) {
982        synchronized(pooledObject) {
983            final PooledObjectState state = pooledObject.getState();
984            if (state != PooledObjectState.ALLOCATED) {
985                throw new IllegalStateException(
986                        "Object has already been returned to this pool or is invalid");
987            }
988            pooledObject.markReturning(); // Keep from being marked abandoned
989        }
990    }
991
992    /**
993     * Sets whether to block when the {@code borrowObject()} method is
994     * invoked when the pool is exhausted (the maximum number of "active"
995     * objects has been reached).
996     *
997     * @param blockWhenExhausted    {@code true} if
998     *                              {@code borrowObject()} should block
999     *                              when the pool is exhausted
1000     *
1001     * @see #getBlockWhenExhausted
1002     */
1003    public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
1004        this.blockWhenExhausted = blockWhenExhausted;
1005    }
1006    /**
1007     * Initializes the receiver with the given configuration.
1008     *
1009     * @param config Initialization source.
1010     */
1011    protected void setConfig(final BaseObjectPoolConfig<T> config) {
1012        setLifo(config.getLifo());
1013        setMaxWaitMillis(config.getMaxWaitMillis());
1014        setBlockWhenExhausted(config.getBlockWhenExhausted());
1015        setTestOnCreate(config.getTestOnCreate());
1016        setTestOnBorrow(config.getTestOnBorrow());
1017        setTestOnReturn(config.getTestOnReturn());
1018        setTestWhileIdle(config.getTestWhileIdle());
1019        setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
1020        setMinEvictableIdleTime(config.getMinEvictableIdleTime());
1021        setTimeBetweenEvictionRuns(config.getTimeBetweenEvictionRuns());
1022        setSoftMinEvictableIdleTime(config.getSoftMinEvictableIdleTime());
1023        final EvictionPolicy<T> policy = config.getEvictionPolicy();
1024        if (policy == null) {
1025            // Use the class name (pre-2.6.0 compatible)
1026            setEvictionPolicyClassName(config.getEvictionPolicyClassName());
1027        } else {
1028            // Otherwise, use the class (2.6.0 feature)
1029            setEvictionPolicy(policy);
1030        }
1031        setEvictorShutdownTimeout(config.getEvictorShutdownTimeout());
1032    }
1033
1034
1035    // Monitoring (primarily JMX) related methods
1036
1037    /**
1038     * Sets the eviction policy for this pool.
1039     *
1040     * @param evictionPolicy
1041     *            the eviction policy for this pool.
1042     * @since 2.6.0
1043     */
1044    public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
1045        this.evictionPolicy = evictionPolicy;
1046    }
1047
1048    /**
1049     * Sets the eviction policy.
1050     *
1051     * @param className Eviction policy class name.
1052     * @param classLoader Load the class from this class loader.
1053     */
1054    @SuppressWarnings("unchecked")
1055    private void setEvictionPolicy(final String className, final ClassLoader classLoader)
1056            throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
1057        final Class<?> clazz = Class.forName(className, true, classLoader);
1058        final Object policy = clazz.getConstructor().newInstance();
1059        this.evictionPolicy = (EvictionPolicy<T>) policy;
1060    }
1061
1062    /**
1063     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1064     * load the class using the thread context class loader. If that fails, the use the class loader for the
1065     * {@link EvictionPolicy} interface.
1066     *
1067     * @param evictionPolicyClassName
1068     *            the fully qualified class name of the new eviction policy
1069     *
1070     * @see #getEvictionPolicyClassName()
1071     * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
1072     *        {@link EvictionPolicy} interface.
1073     */
1074    public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
1075        setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
1076    }
1077
1078    /**
1079     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1080     * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
1081     * interface.
1082     *
1083     * @param evictionPolicyClassName
1084     *            the fully qualified class name of the new eviction policy
1085     * @param classLoader
1086     *            the class loader to load the given {@code evictionPolicyClassName}.
1087     *
1088     * @see #getEvictionPolicyClassName()
1089     * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
1090     *        {@link EvictionPolicy} interface.
1091     */
1092    public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
1093        // Getting epClass here and now best matches the caller's environment
1094        final Class<?> epClass = EvictionPolicy.class;
1095        final ClassLoader epClassLoader = epClass.getClassLoader();
1096        try {
1097            try {
1098                setEvictionPolicy(evictionPolicyClassName, classLoader);
1099            } catch (final ClassCastException | ClassNotFoundException e) {
1100                setEvictionPolicy(evictionPolicyClassName, epClassLoader);
1101            }
1102        } catch (final ClassCastException e) {
1103            throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
1104                    classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
1105        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
1106                InvocationTargetException | NoSuchMethodException e) {
1107            final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " +
1108                    evictionPolicyClassName;
1109            throw new IllegalArgumentException(exMessage, e);
1110        }
1111    }
1112
1113    /**
1114     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1115     * only pool still using the the value for the Evictor.
1116     *
1117     * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
1118     *                                     to shut down.
1119     * @since 2.10.0
1120     */
1121    public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeoutMillis) {
1122        this.evictorShutdownTimeout = evictorShutdownTimeoutMillis;
1123    }
1124
1125    /**
1126     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1127     * only pool still using the the value for the Evictor.
1128     *
1129     * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
1130     *                                     to shut down.
1131     * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
1132     */
1133    @Deprecated
1134    public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
1135        this.evictorShutdownTimeout = Duration.ofMillis(evictorShutdownTimeoutMillis);
1136    }
1137
1138    /**
1139     * Sets whether the pool has LIFO (last in, first out) behavior with
1140     * respect to idle objects - always returning the most recently used object
1141     * from the pool, or as a FIFO (first in, first out) queue, where the pool
1142     * always returns the oldest object in the idle object pool.
1143     *
1144     * @param lifo  {@code true} if the pool is to be configured with LIFO
1145     *              behavior or {@code false} if the pool is to be
1146     *              configured with FIFO behavior
1147     *
1148     * @see #getLifo()
1149     */
1150    public final void setLifo(final boolean lifo) {
1151        this.lifo = lifo;
1152    }
1153
1154    /**
1155     * Sets the cap on the number of objects that can be allocated by the pool
1156     * (checked out to clients, or idle awaiting checkout) at a given time. Use
1157     * a negative value for no limit.
1158     *
1159     * @param maxTotal  The cap on the total number of object instances managed
1160     *                  by the pool. Negative values mean that there is no limit
1161     *                  to the number of objects allocated by the pool.
1162     *
1163     * @see #getMaxTotal
1164     */
1165    public final void setMaxTotal(final int maxTotal) {
1166        this.maxTotal = maxTotal;
1167    }
1168
1169    /**
1170     * Sets the maximum amount of time (in milliseconds) the
1171     * {@code borrowObject()} method should block before throwing an
1172     * exception when the pool is exhausted and
1173     * {@link #getBlockWhenExhausted} is true. When less than 0, the
1174     * {@code borrowObject()} method may block indefinitely.
1175     *
1176     * @param maxWaitMillis the maximum number of milliseconds
1177     *                      {@code borrowObject()} will block or negative
1178     *                      for indefinitely.
1179     *
1180     * @see #getMaxWaitMillis
1181     * @see #setBlockWhenExhausted
1182     */
1183    public final void setMaxWaitMillis(final long maxWaitMillis) {
1184        this.maxWait = Duration.ofMillis(maxWaitMillis);
1185    }
1186
1187    /**
1188     * Sets the minimum amount of time an object may sit idle in the pool
1189     * before it is eligible for eviction by the idle object evictor (if any -
1190     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
1191     * no objects will be evicted from the pool due to idle time alone.
1192     *
1193     * @param minEvictableIdleTimeMillis
1194     *            minimum amount of time an object may sit idle in the pool
1195     *            before it is eligible for eviction
1196     *
1197     * @see #getMinEvictableIdleTime
1198     * @see #setTimeBetweenEvictionRuns
1199     * @since 2.10.0
1200     */
1201    public final void setMinEvictableIdleTime(final Duration minEvictableIdleTimeMillis) {
1202        this.minEvictableIdleTime = minEvictableIdleTimeMillis;
1203    }
1204
1205    /**
1206     * Sets the minimum amount of time an object may sit idle in the pool
1207     * before it is eligible for eviction by the idle object evictor (if any -
1208     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
1209     * no objects will be evicted from the pool due to idle time alone.
1210     *
1211     * @param minEvictableIdleTimeMillis
1212     *            minimum amount of time an object may sit idle in the pool
1213     *            before it is eligible for eviction
1214     *
1215     * @see #getMinEvictableIdleTimeMillis
1216     * @see #setTimeBetweenEvictionRunsMillis
1217     * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
1218     */
1219    @Deprecated
1220    public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
1221        this.minEvictableIdleTime = Duration.ofMillis(minEvictableIdleTimeMillis);
1222    }
1223
1224    /**
1225     * Sets the maximum number of objects to examine during each run (if any)
1226     * of the idle object evictor thread. When positive, the number of tests
1227     * performed for a run will be the minimum of the configured value and the
1228     * number of idle instances in the pool. When negative, the number of tests
1229     * performed will be <code>ceil({@link #getNumIdle}/
1230     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
1231     * value is {@code -n} roughly one nth of the idle objects will be
1232     * tested per run.
1233     *
1234     * @param numTestsPerEvictionRun
1235     *            max number of objects to examine during each evictor run
1236     *
1237     * @see #getNumTestsPerEvictionRun
1238     * @see #setTimeBetweenEvictionRunsMillis
1239     */
1240    public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
1241        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
1242    }
1243
1244    /**
1245     * Sets the minimum amount of time an object may sit idle in the pool
1246     * before it is eligible for eviction by the idle object evictor (if any -
1247     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
1248     * with the extra condition that at least {@code minIdle} object
1249     * instances remain in the pool. This setting is overridden by
1250     * {@link #getMinEvictableIdleTime} (that is, if
1251     * {@link #getMinEvictableIdleTime} is positive, then
1252     * {@link #getSoftMinEvictableIdleTime} is ignored).
1253     *
1254     * @param softMinEvictableIdleTime
1255     *            minimum amount of time an object may sit idle in the pool
1256     *            before it is eligible for eviction if minIdle instances are
1257     *            available
1258     *
1259     * @see #getSoftMinEvictableIdleTimeMillis
1260     * @since 2.10.0
1261     */
1262    public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
1263        this.softMinEvictableIdleTime = softMinEvictableIdleTime;
1264    }
1265
1266    /**
1267     * Sets the minimum amount of time an object may sit idle in the pool
1268     * before it is eligible for eviction by the idle object evictor (if any -
1269     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
1270     * with the extra condition that at least {@code minIdle} object
1271     * instances remain in the pool. This setting is overridden by
1272     * {@link #getMinEvictableIdleTimeMillis} (that is, if
1273     * {@link #getMinEvictableIdleTimeMillis} is positive, then
1274     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
1275     *
1276     * @param softMinEvictableIdleTimeMillis
1277     *            minimum amount of time an object may sit idle in the pool
1278     *            before it is eligible for eviction if minIdle instances are
1279     *            available
1280     *
1281     * @see #getSoftMinEvictableIdleTimeMillis
1282     * @deprecated Use {@link #setSoftMinEvictableIdleTime(Duration)}.
1283     */
1284    @Deprecated
1285    public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
1286        this.softMinEvictableIdleTime = Duration.ofMillis(softMinEvictableIdleTimeMillis);
1287    }
1288
1289    /**
1290     * The listener used (if any) to receive notifications of exceptions
1291     * unavoidably swallowed by the pool.
1292     *
1293     * @param swallowedExceptionListener    The listener or {@code null}
1294     *                                      for no listener
1295     */
1296    public final void setSwallowedExceptionListener(
1297            final SwallowedExceptionListener swallowedExceptionListener) {
1298        this.swallowedExceptionListener = swallowedExceptionListener;
1299    }
1300
1301    /**
1302     * Sets whether objects borrowed from the pool will be validated before
1303     * being returned from the {@code borrowObject()} method. Validation is
1304     * performed by the {@code validateObject()} method of the factory
1305     * associated with the pool. If the object fails to validate, it will be
1306     * removed from the pool and destroyed, and a new attempt will be made to
1307     * borrow an object from the pool.
1308     *
1309     * @param testOnBorrow  {@code true} if objects should be validated
1310     *                      before being returned from the
1311     *                      {@code borrowObject()} method
1312     *
1313     * @see #getTestOnBorrow
1314     */
1315    public final void setTestOnBorrow(final boolean testOnBorrow) {
1316        this.testOnBorrow = testOnBorrow;
1317    }
1318
1319    /**
1320     * Sets whether objects created for the pool will be validated before
1321     * being returned from the {@code borrowObject()} method. Validation is
1322     * performed by the {@code validateObject()} method of the factory
1323     * associated with the pool. If the object fails to validate, then
1324     * {@code borrowObject()} will fail.
1325     *
1326     * @param testOnCreate  {@code true} if newly created objects should be
1327     *                      validated before being returned from the
1328     *                      {@code borrowObject()} method
1329     *
1330     * @see #getTestOnCreate
1331     *
1332     * @since 2.2
1333     */
1334    public final void setTestOnCreate(final boolean testOnCreate) {
1335        this.testOnCreate = testOnCreate;
1336    }
1337
1338    /**
1339     * Sets whether objects borrowed from the pool will be validated when
1340     * they are returned to the pool via the {@code returnObject()} method.
1341     * Validation is performed by the {@code validateObject()} method of
1342     * the factory associated with the pool. Returning objects that fail validation
1343     * are destroyed rather then being returned the pool.
1344     *
1345     * @param testOnReturn {@code true} if objects are validated on
1346     *                     return to the pool via the
1347     *                     {@code returnObject()} method
1348     *
1349     * @see #getTestOnReturn
1350     */
1351    public final void setTestOnReturn(final boolean testOnReturn) {
1352        this.testOnReturn = testOnReturn;
1353    }
1354
1355    /**
1356     * Sets whether objects sitting idle in the pool will be validated by the
1357     * idle object evictor (if any - see
1358     * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
1359     * by the {@code validateObject()} method of the factory associated
1360     * with the pool. If the object fails to validate, it will be removed from
1361     * the pool and destroyed.  Note that setting this property has no effect
1362     * unless the idle object evictor is enabled by setting
1363     * {@code timeBetweenEvictionRunsMillis} to a positive value.
1364     *
1365     * @param testWhileIdle
1366     *            {@code true} so objects will be validated by the evictor
1367     *
1368     * @see #getTestWhileIdle
1369     * @see #setTimeBetweenEvictionRuns
1370     */
1371    public final void setTestWhileIdle(final boolean testWhileIdle) {
1372        this.testWhileIdle = testWhileIdle;
1373    }
1374
1375    /**
1376     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1377     * <ul>
1378     * <li>When positive, the idle object evictor thread starts.</li>
1379     * <li>When non-positive, no idle object evictor thread runs.</li>
1380     * </ul>
1381     *
1382     * @param timeBetweenEvictionRuns
1383     *            duration to sleep between evictor runs
1384     *
1385     * @see #getTimeBetweenEvictionRunsMillis
1386     * @since 2.10.0
1387     */
1388    public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
1389        this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
1390        startEvictor(this.timeBetweenEvictionRuns);
1391    }
1392
1393    /**
1394     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1395     * <ul>
1396     * <li>When positive, the idle object evictor thread starts.</li>
1397     * <li>When non-positive, no idle object evictor thread runs.</li>
1398     * </ul>
1399     *
1400     * @param timeBetweenEvictionRunsMillis
1401     *            number of milliseconds to sleep between evictor runs
1402     *
1403     * @see #getTimeBetweenEvictionRunsMillis
1404     * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}.
1405     */
1406    @Deprecated
1407    public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
1408        this.timeBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis);
1409        startEvictor(timeBetweenEvictionRuns);
1410    }
1411
1412    /**
1413     * <p>Starts the evictor with the given delay. If there is an evictor
1414     * running when this method is called, it is stopped and replaced with a
1415     * new evictor with the specified delay.</p>
1416     *
1417     * <p>This method needs to be final, since it is called from a constructor.
1418     * See POOL-195.</p>
1419     *
1420     * @param delay time in milliseconds before start and between eviction runs
1421     */
1422    final void startEvictor(final Duration delay) {
1423        synchronized (evictionLock) {
1424            final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
1425            if (evictor == null) { // Starting evictor for the first time or after a cancel
1426                if (isPositiverDelay) {   // Starting new evictor
1427                    evictor = new Evictor();
1428                    EvictionTimer.schedule(evictor, delay, delay);
1429                }
1430            } else {  // Stop or restart of existing evictor
1431                if (isPositiverDelay) { // Restart
1432                    synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
1433                        EvictionTimer.cancel(evictor, evictorShutdownTimeout, true);
1434                        evictor = null;
1435                        evictionIterator = null;
1436                        evictor = new Evictor();
1437                        EvictionTimer.schedule(evictor, delay, delay);
1438                    }
1439                } else { // Stopping evictor
1440                    EvictionTimer.cancel(evictor, evictorShutdownTimeout, false);
1441                }
1442            }
1443        }
1444    }
1445
1446
1447
1448    // Inner classes
1449
1450    /**
1451     * Stops the evictor.
1452     */
1453    void stopEvictor() {
1454        startEvictor(Duration.ofMillis(-1L));
1455    }
1456
1457    /**
1458     * Swallows an exception and notifies the configured listener for swallowed
1459     * exceptions queue.
1460     *
1461     * @param swallowException exception to be swallowed
1462     */
1463    final void swallowException(final Exception swallowException) {
1464        final SwallowedExceptionListener listener = getSwallowedExceptionListener();
1465
1466        if (listener == null) {
1467            return;
1468        }
1469
1470        try {
1471            listener.onSwallowException(swallowException);
1472        } catch (final VirtualMachineError e) {
1473            throw e;
1474        } catch (final Throwable t) {
1475            // Ignore. Enjoy the irony.
1476        }
1477    }
1478
1479    @Override
1480    protected void toStringAppendFields(final StringBuilder builder) {
1481        builder.append("maxTotal=");
1482        builder.append(maxTotal);
1483        builder.append(", blockWhenExhausted=");
1484        builder.append(blockWhenExhausted);
1485        builder.append(", maxWaitMillis=");
1486        builder.append(maxWait);
1487        builder.append(", lifo=");
1488        builder.append(lifo);
1489        builder.append(", fairness=");
1490        builder.append(fairness);
1491        builder.append(", testOnCreate=");
1492        builder.append(testOnCreate);
1493        builder.append(", testOnBorrow=");
1494        builder.append(testOnBorrow);
1495        builder.append(", testOnReturn=");
1496        builder.append(testOnReturn);
1497        builder.append(", testWhileIdle=");
1498        builder.append(testWhileIdle);
1499        builder.append(", timeBetweenEvictionRunsMillis=");
1500        builder.append(timeBetweenEvictionRuns);
1501        builder.append(", numTestsPerEvictionRun=");
1502        builder.append(numTestsPerEvictionRun);
1503        builder.append(", minEvictableIdleTimeMillis=");
1504        builder.append(minEvictableIdleTime);
1505        builder.append(", softMinEvictableIdleTimeMillis=");
1506        builder.append(softMinEvictableIdleTime);
1507        builder.append(", evictionPolicy=");
1508        builder.append(evictionPolicy);
1509        builder.append(", closeLock=");
1510        builder.append(closeLock);
1511        builder.append(", closed=");
1512        builder.append(closed);
1513        builder.append(", evictionLock=");
1514        builder.append(evictionLock);
1515        builder.append(", evictor=");
1516        builder.append(evictor);
1517        builder.append(", evictionIterator=");
1518        builder.append(evictionIterator);
1519        builder.append(", factoryClassLoader=");
1520        builder.append(factoryClassLoader);
1521        builder.append(", oname=");
1522        builder.append(objectName);
1523        builder.append(", creationStackTrace=");
1524        builder.append(creationStackTrace);
1525        builder.append(", borrowedCount=");
1526        builder.append(borrowedCount);
1527        builder.append(", returnedCount=");
1528        builder.append(returnedCount);
1529        builder.append(", createdCount=");
1530        builder.append(createdCount);
1531        builder.append(", destroyedCount=");
1532        builder.append(destroyedCount);
1533        builder.append(", destroyedByEvictorCount=");
1534        builder.append(destroyedByEvictorCount);
1535        builder.append(", destroyedByBorrowValidationCount=");
1536        builder.append(destroyedByBorrowValidationCount);
1537        builder.append(", activeTimes=");
1538        builder.append(activeTimes);
1539        builder.append(", idleTimes=");
1540        builder.append(idleTimes);
1541        builder.append(", waitTimes=");
1542        builder.append(waitTimes);
1543        builder.append(", maxBorrowWaitTimeMillis=");
1544        builder.append(maxBorrowWaitTimeMillis);
1545        builder.append(", swallowedExceptionListener=");
1546        builder.append(swallowedExceptionListener);
1547    }
1548
1549    /**
1550     * Updates statistics after an object is borrowed from the pool.
1551     *
1552     * @param p object borrowed from the pool
1553     * @param waitTime time (in milliseconds) that the borrowing thread had to wait
1554     */
1555    final void updateStatsBorrow(final PooledObject<T> p, final Duration waitTime) {
1556        borrowedCount.incrementAndGet();
1557        idleTimes.add(p.getIdleTime());
1558        waitTimes.add(waitTime);
1559        final long waitTimeMillis = waitTime.toMillis();
1560
1561        // lock-free optimistic-locking maximum
1562        long currentMaxMillis;
1563        do {
1564            currentMaxMillis = maxBorrowWaitTimeMillis.get();
1565            if (currentMaxMillis >= waitTimeMillis) {
1566                break;
1567            }
1568        } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMaxMillis, waitTimeMillis));
1569    }
1570
1571    /**
1572     * Updates statistics after an object is returned to the pool.
1573     *
1574     * @param activeTime the amount of time (in milliseconds) that the returning
1575     * object was checked out
1576     */
1577    final void updateStatsReturn(final Duration activeTime) {
1578        returnedCount.incrementAndGet();
1579        activeTimes.add(activeTime);
1580    }
1581
1582
1583}