GenericObjectPool.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.pool2.impl;

  18. import java.time.Duration;
  19. import java.time.Instant;
  20. import java.util.ArrayList;
  21. import java.util.NoSuchElementException;
  22. import java.util.Set;
  23. import java.util.concurrent.ConcurrentHashMap;
  24. import java.util.concurrent.atomic.AtomicLong;
  25. import java.util.stream.Collectors;

  26. import org.apache.commons.pool2.DestroyMode;
  27. import org.apache.commons.pool2.ObjectPool;
  28. import org.apache.commons.pool2.PoolUtils;
  29. import org.apache.commons.pool2.PooledObject;
  30. import org.apache.commons.pool2.PooledObjectFactory;
  31. import org.apache.commons.pool2.PooledObjectState;
  32. import org.apache.commons.pool2.SwallowedExceptionListener;
  33. import org.apache.commons.pool2.TrackedUse;
  34. import org.apache.commons.pool2.UsageTracking;

  35. /**
  36.  * A configurable {@link ObjectPool} implementation.
  37.  * <p>
  38.  * When coupled with the appropriate {@link PooledObjectFactory},
  39.  * {@code GenericObjectPool} provides robust pooling functionality for
  40.  * arbitrary objects.
  41.  * </p>
  42.  * <p>
  43.  * Optionally, one may configure the pool to examine and possibly evict objects
  44.  * as they sit idle in the pool and to ensure that a minimum number of idle
  45.  * objects are available. This is performed by an "idle object eviction" thread,
  46.  * which runs asynchronously. Caution should be used when configuring this
  47.  * optional feature. Eviction runs contend with client threads for access to
  48.  * objects in the pool, so if they run too frequently performance issues may
  49.  * result.
  50.  * </p>
  51.  * <p>
  52.  * The pool can also be configured to detect and remove "abandoned" objects,
  53.  * i.e. objects that have been checked out of the pool but neither used nor
  54.  * returned before the configured
  55.  * {@link AbandonedConfig#getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout}.
  56.  * Abandoned object removal can be configured to happen when
  57.  * {@code borrowObject} is invoked and the pool is close to starvation, or
  58.  * it can be executed by the idle object evictor, or both. If pooled objects
  59.  * implement the {@link TrackedUse} interface, their last use will be queried
  60.  * using the {@code getLastUsed} method on that interface; otherwise
  61.  * abandonment is determined by how long an object has been checked out from
  62.  * the pool.
  63.  * </p>
  64.  * <p>
  65.  * Implementation note: To prevent possible deadlocks, care has been taken to
  66.  * ensure that no call to a factory method will occur within a synchronization
  67.  * block. See POOL-125 and DBCP-44 for more information.
  68.  * </p>
  69.  * <p>
  70.  * This class is intended to be thread-safe.
  71.  * </p>
  72.  *
  73.  * @see GenericKeyedObjectPool
  74.  * @param <T> Type of element pooled in this pool.
  75.  * @since 2.0
  76.  */
  77. public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
  78.         implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {

  79.     // JMX specific attributes
  80.     private static final String ONAME_BASE =
  81.         "org.apache.commons.pool2:type=GenericObjectPool,name=";

  82.     private static void wait(final Object obj, final Duration duration) throws InterruptedException {
  83.         if (!duration.isNegative()) {
  84.             obj.wait(duration.toMillis(), duration.getNano() % 1_000_000);
  85.         }
  86.     }

  87.     private volatile String factoryType;

  88.     private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;

  89.     private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;

  90.     private final PooledObjectFactory<T> factory;

  91.     /*
  92.      * All of the objects currently associated with this pool in any state. It
  93.      * excludes objects that have been destroyed. The size of
  94.      * {@link #allObjects} will always be less than or equal to {@link
  95.      * #_maxActive}. Map keys are pooled objects, values are the PooledObject
  96.      * wrappers used internally by the pool.
  97.      */
  98.     private final ConcurrentHashMap<IdentityWrapper<T>, PooledObject<T>> allObjects = new ConcurrentHashMap<>();

  99.     /*
  100.      * The combined count of the currently created objects and those in the
  101.      * process of being created. Under load, it may exceed {@link #_maxActive}
  102.      * if multiple threads try and create a new object at the same time but
  103.      * {@link #create()} will ensure that there are never more than
  104.      * {@link #_maxActive} objects created at any one time.
  105.      */
  106.     private final AtomicLong createCount = new AtomicLong();

  107.     private long makeObjectCount;

  108.     private final Object makeObjectCountLock = new Object();

  109.     private final LinkedBlockingDeque<PooledObject<T>> idleObjects;

  110.     /**
  111.      * Creates a new {@code GenericObjectPool} using defaults from
  112.      * {@link GenericObjectPoolConfig}.
  113.      *
  114.      * @param factory The object factory to be used to create object instances
  115.      *                used by this pool
  116.      */
  117.     public GenericObjectPool(final PooledObjectFactory<T> factory) {
  118.         this(factory, new GenericObjectPoolConfig<>());
  119.     }

  120.     /**
  121.      * Creates a new {@code GenericObjectPool} using a specific
  122.      * configuration.
  123.      *
  124.      * @param factory   The object factory to be used to create object instances
  125.      *                  used by this pool
  126.      * @param config    The configuration to use for this pool instance. The
  127.      *                  configuration is used by value. Subsequent changes to
  128.      *                  the configuration object will not be reflected in the
  129.      *                  pool.
  130.      */
  131.     public GenericObjectPool(final PooledObjectFactory<T> factory,
  132.             final GenericObjectPoolConfig<T> config) {

  133.         super(config, ONAME_BASE, config.getJmxNamePrefix());

  134.         if (factory == null) {
  135.             jmxUnregister(); // tidy up
  136.             throw new IllegalArgumentException("Factory may not be null");
  137.         }
  138.         this.factory = factory;

  139.         idleObjects = new LinkedBlockingDeque<>(config.getFairness());

  140.         setConfig(config);
  141.     }

  142.     /**
  143.      * Creates a new {@code GenericObjectPool} that tracks and destroys
  144.      * objects that are checked out, but never returned to the pool.
  145.      *
  146.      * @param factory   The object factory to be used to create object instances
  147.      *                  used by this pool
  148.      * @param config    The base pool configuration to use for this pool instance.
  149.      *                  The configuration is used by value. Subsequent changes to
  150.      *                  the configuration object will not be reflected in the
  151.      *                  pool.
  152.      * @param abandonedConfig  Configuration for abandoned object identification
  153.      *                         and removal.  The configuration is used by value.
  154.      */
  155.     public GenericObjectPool(final PooledObjectFactory<T> factory,
  156.             final GenericObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
  157.         this(factory, config);
  158.         setAbandonedConfig(abandonedConfig);
  159.     }

  160.     /**
  161.      * Adds the provided wrapped pooled object to the set of idle objects for
  162.      * this pool. The object must already be part of the pool.  If {@code p}
  163.      * is null, this is a no-op (no exception, but no impact on the pool).
  164.      *
  165.      * @param p The object to make idle
  166.      * @throws Exception If the factory fails to passivate the object
  167.      */
  168.     private void addIdleObject(final PooledObject<T> p) throws Exception {
  169.         if (!PooledObject.isNull(p)) {
  170.             factory.passivateObject(p);
  171.             if (getLifo()) {
  172.                 idleObjects.addFirst(p);
  173.             } else {
  174.                 idleObjects.addLast(p);
  175.             }
  176.         }
  177.     }

  178.     /**
  179.      * Creates an object, and place it into the pool. addObject() is useful for
  180.      * "pre-loading" a pool with idle objects.
  181.      * <p>
  182.      * If there is no capacity available to add to the pool, this is a no-op
  183.      * (no exception, no impact to the pool).
  184.      * </p>
  185.      * <p>
  186.      * If the factory returns null when creating an object, a {@code NullPointerException}
  187.      * is thrown. If there is no factory set (factory == null), an {@code IllegalStateException}
  188.      * is thrown.
  189.      * </p>
  190.      */
  191.     @Override
  192.     public void addObject() throws Exception {
  193.         assertOpen();
  194.         if (factory == null) {
  195.             throw new IllegalStateException("Cannot add objects without a factory.");
  196.         }
  197.         addIdleObject(create(getMaxWaitDuration()));
  198.     }

  199.     /**
  200.      * Equivalent to <code>{@link #borrowObject(long)
  201.      * borrowObject}({@link #getMaxWaitDuration()})</code>.
  202.      *
  203.      * {@inheritDoc}
  204.      */
  205.     @Override
  206.     public T borrowObject() throws Exception {
  207.         return borrowObject(getMaxWaitDuration());
  208.     }

  209.     /**
  210.      * Borrows an object from the pool using the specific waiting time which only
  211.      * applies if {@link #getBlockWhenExhausted()} is true.
  212.      * <p>
  213.      * If there is one or more idle instance available in the pool, then an
  214.      * idle instance will be selected based on the value of {@link #getLifo()},
  215.      * activated and returned. If activation fails, or {@link #getTestOnBorrow()
  216.      * testOnBorrow} is set to {@code true} and validation fails, the
  217.      * instance is destroyed and the next available instance is examined. This
  218.      * continues until either a valid instance is returned or there are no more
  219.      * idle instances available.
  220.      * </p>
  221.      * <p>
  222.      * If there are no idle instances available in the pool, behavior depends on
  223.      * the {@link #getMaxTotal() maxTotal}, (if applicable)
  224.      * {@link #getBlockWhenExhausted()} and the value passed in the
  225.      * {@code maxWaitDuration} parameter. If the number of instances
  226.      * checked out from the pool is less than {@code maxTotal,} a new
  227.      * instance is created, activated and (if applicable) validated and returned
  228.      * to the caller. If validation fails, a {@code NoSuchElementException}
  229.      * is thrown. If the factory returns null when creating an instance,
  230.      * a {@code NullPointerException} is thrown.
  231.      * </p>
  232.      * <p>
  233.      * If the pool is exhausted (no available idle instances and no capacity to
  234.      * create new ones), this method will either block (if
  235.      * {@link #getBlockWhenExhausted()} is true) or throw a
  236.      * {@code NoSuchElementException} (if
  237.      * {@link #getBlockWhenExhausted()} is false). The length of time that this
  238.      * method will block when {@link #getBlockWhenExhausted()} is true is
  239.      * determined by the value passed in to the {@code maxWaitDuration}
  240.      * parameter.
  241.      * </p>
  242.      * <p>
  243.      * When the pool is exhausted, multiple calling threads may be
  244.      * simultaneously blocked waiting for instances to become available. A
  245.      * "fairness" algorithm has been implemented to ensure that threads receive
  246.      * available instances in request arrival order.
  247.      * </p>
  248.      *
  249.      * @param maxWaitDuration The time to wait for an object to become available, not null.
  250.      * @return object instance from the pool
  251.      * @throws NoSuchElementException if an instance cannot be returned
  252.      * @throws Exception if an object instance cannot be returned due to an error
  253.      * @since 2.10.0
  254.      */
  255.     public T borrowObject(final Duration maxWaitDuration) throws Exception {
  256.         assertOpen();
  257.         final Instant startInstant = Instant.now();
  258.         final boolean negativeDuration = maxWaitDuration.isNegative();
  259.         Duration remainingWaitDuration = maxWaitDuration;
  260.         final AbandonedConfig ac = this.abandonedConfig;
  261.         if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 && getNumActive() > getMaxTotal() - 3) {
  262.             removeAbandoned(ac);
  263.         }
  264.         PooledObject<T> p = null;
  265.         // Get local copy of current config so it is consistent for entire
  266.         // method execution
  267.         final boolean blockWhenExhausted = getBlockWhenExhausted();
  268.         boolean create;
  269.         while (p == null) {
  270.             remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant));
  271.             create = false;
  272.             p = idleObjects.pollFirst();
  273.             if (p == null) {
  274.                 p = create(remainingWaitDuration);
  275.                 if (!PooledObject.isNull(p)) {
  276.                     create = true;
  277.                 }
  278.             }
  279.             if (blockWhenExhausted) {
  280.                 if (PooledObject.isNull(p)) {
  281.                     remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant));
  282.                     p = negativeDuration ? idleObjects.takeFirst() : idleObjects.pollFirst(remainingWaitDuration);
  283.                 }
  284.                 if (PooledObject.isNull(p)) {
  285.                     throw new NoSuchElementException(appendStats("Timeout waiting for idle object, maxWaitDuration=" + remainingWaitDuration));
  286.                 }
  287.             } else if (PooledObject.isNull(p)) {
  288.                 throw new NoSuchElementException(appendStats("Pool exhausted"));
  289.             }
  290.             if (!p.allocate()) {
  291.                 p = null;
  292.             }
  293.             if (!PooledObject.isNull(p)) {
  294.                 try {
  295.                     factory.activateObject(p);
  296.                 } catch (final Exception e) {
  297.                     try {
  298.                         destroy(p, DestroyMode.NORMAL);
  299.                     } catch (final Exception ignored) {
  300.                         // ignored - activation failure is more important
  301.                     }
  302.                     p = null;
  303.                     if (create) {
  304.                         final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object"));
  305.                         nsee.initCause(e);
  306.                         throw nsee;
  307.                     }
  308.                 }
  309.                 if (!PooledObject.isNull(p) && getTestOnBorrow()) {
  310.                     boolean validate = false;
  311.                     Throwable validationThrowable = null;
  312.                     try {
  313.                         validate = factory.validateObject(p);
  314.                     } catch (final Throwable t) {
  315.                         PoolUtils.checkRethrow(t);
  316.                         validationThrowable = t;
  317.                     }
  318.                     if (!validate) {
  319.                         try {
  320.                             destroy(p, DestroyMode.NORMAL);
  321.                             destroyedByBorrowValidationCount.incrementAndGet();
  322.                         } catch (final Exception ignored) {
  323.                             // ignored - validation failure is more important
  324.                         }
  325.                         p = null;
  326.                         if (create) {
  327.                             final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to validate object"));
  328.                             nsee.initCause(validationThrowable);
  329.                             throw nsee;
  330.                         }
  331.                     }
  332.                 }
  333.             }
  334.         }
  335.         updateStatsBorrow(p, durationSince(startInstant));
  336.         return p.getObject();
  337.     }

  338.     /**
  339.      * Borrows an object from the pool using the specific waiting time which only
  340.      * applies if {@link #getBlockWhenExhausted()} is true.
  341.      * <p>
  342.      * If there is one or more idle instance available in the pool, then an
  343.      * idle instance will be selected based on the value of {@link #getLifo()},
  344.      * activated and returned. If activation fails, or {@link #getTestOnBorrow()
  345.      * testOnBorrow} is set to {@code true} and validation fails, the
  346.      * instance is destroyed and the next available instance is examined. This
  347.      * continues until either a valid instance is returned or there are no more
  348.      * idle instances available.
  349.      * </p>
  350.      * <p>
  351.      * If there are no idle instances available in the pool, behavior depends on
  352.      * the {@link #getMaxTotal() maxTotal}, (if applicable)
  353.      * {@link #getBlockWhenExhausted()} and the value passed in to the
  354.      * {@code maxWaitMillis} parameter. If the number of instances
  355.      * checked out from the pool is less than {@code maxTotal,} a new
  356.      * instance is created, activated and (if applicable) validated and returned
  357.      * to the caller. If validation fails, a {@code NoSuchElementException}
  358.      * is thrown. If the factory returns null when creating an instance,
  359.      * a {@code NullPointerException} is thrown.
  360.      * </p>
  361.      * <p>
  362.      * If the pool is exhausted (no available idle instances and no capacity to
  363.      * create new ones), this method will either block (if
  364.      * {@link #getBlockWhenExhausted()} is true) or throw a
  365.      * {@code NoSuchElementException} (if
  366.      * {@link #getBlockWhenExhausted()} is false). The length of time that this
  367.      * method will block when {@link #getBlockWhenExhausted()} is true is
  368.      * determined by the value passed in to the {@code maxWaitMillis}
  369.      * parameter.
  370.      * </p>
  371.      * <p>
  372.      * When the pool is exhausted, multiple calling threads may be
  373.      * simultaneously blocked waiting for instances to become available. A
  374.      * "fairness" algorithm has been implemented to ensure that threads receive
  375.      * available instances in request arrival order.
  376.      * </p>
  377.      *
  378.      * @param maxWaitMillis The time to wait in milliseconds for an object
  379.      *                            to become available
  380.      * @return object instance from the pool
  381.      * @throws NoSuchElementException if an instance cannot be returned
  382.      * @throws Exception if an object instance cannot be returned due to an
  383.      *                   error
  384.      */
  385.     public T borrowObject(final long maxWaitMillis) throws Exception {
  386.         return borrowObject(Duration.ofMillis(maxWaitMillis));
  387.     }

  388.     /**
  389.      * Clears any objects sitting idle in the pool by removing them from the
  390.      * idle instance pool and then invoking the configured
  391.      * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
  392.      * idle instance.
  393.      * <p>
  394.      * Implementation notes:
  395.      * </p>
  396.      * <ul>
  397.      * <li>This method does not destroy or effect in any way instances that are
  398.      * checked out of the pool when it is invoked.</li>
  399.      * <li>Invoking this method does not prevent objects being returned to the
  400.      * idle instance pool, even during its execution. Additional instances may
  401.      * be returned while removed items are being destroyed.</li>
  402.      * <li>Exceptions encountered destroying idle instances are swallowed
  403.      * but notified via a {@link SwallowedExceptionListener}.</li>
  404.      * </ul>
  405.      */
  406.     @Override
  407.     public void clear() {
  408.         PooledObject<T> p = idleObjects.poll();

  409.         while (p != null) {
  410.             try {
  411.                 destroy(p, DestroyMode.NORMAL);
  412.             } catch (final Exception e) {
  413.                 swallowException(e);
  414.             }
  415.             p = idleObjects.poll();
  416.         }
  417.     }

  418.     /**
  419.      * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
  420.      * fail with IllegalStateException, but {@link #returnObject(Object)} and
  421.      * {@link #invalidateObject(Object)} will continue to work, with returned
  422.      * objects destroyed on return.
  423.      * <p>
  424.      * Destroys idle instances in the pool by invoking {@link #clear()}.
  425.      * </p>
  426.      */
  427.     @Override
  428.     public void close() {
  429.         if (isClosed()) {
  430.             return;
  431.         }

  432.         synchronized (closeLock) {
  433.             if (isClosed()) {
  434.                 return;
  435.             }

  436.             // Stop the evictor before the pool is closed since evict() calls
  437.             // assertOpen()
  438.             stopEvictor();

  439.             closed = true;
  440.             // This clear removes any idle objects
  441.             clear();

  442.             jmxUnregister();

  443.             // Release any threads that were waiting for an object
  444.             idleObjects.interuptTakeWaiters();
  445.         }
  446.     }

  447.     /**
  448.      * Attempts to create a new wrapped pooled object.
  449.      * <p>
  450.      * If there are {@link #getMaxTotal()} objects already in circulation or in process of being created, this method
  451.      * returns null.
  452.      * </p>
  453.      * <p>
  454.      * If the factory makeObject returns null, this method throws a NullPointerException.
  455.      * </p>
  456.      *
  457.      * @param maxWaitDuration The time to wait for an object to become available.
  458.      * @return The new wrapped pooled object or null.
  459.      * @throws Exception if the object factory's {@code makeObject} fails
  460.      */
  461.     private PooledObject<T> create(final Duration maxWaitDuration) throws Exception {
  462.         final Instant startInstant = Instant.now();
  463.         Duration remainingWaitDuration = maxWaitDuration.isNegative() ? Duration.ZERO : maxWaitDuration;
  464.         int localMaxTotal = getMaxTotal();
  465.         // This simplifies the code later in this method
  466.         if (localMaxTotal < 0) {
  467.             localMaxTotal = Integer.MAX_VALUE;
  468.         }
  469.         final Instant localStartInstant = Instant.now();
  470.         // Flag that indicates if create should:
  471.         // - TRUE:  call the factory to create an object
  472.         // - FALSE: return null
  473.         // - null:  loop and re-test the condition that determines whether to
  474.         //          call the factory
  475.         Boolean create = null;
  476.         while (create == null) {
  477.             // remainingWaitDuration handles spurious wakeup from wait().
  478.             remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant));
  479.             synchronized (makeObjectCountLock) {
  480.                 final long newCreateCount = createCount.incrementAndGet();
  481.                 if (newCreateCount > localMaxTotal) {
  482.                     // The pool is currently at capacity or in the process of
  483.                     // making enough new objects to take it to capacity.
  484.                     createCount.decrementAndGet();
  485.                     if (makeObjectCount == 0) {
  486.                         // There are no makeObject() calls in progress so the
  487.                         // pool is at capacity. Do not attempt to create a new
  488.                         // object. Return and wait for an object to be returned
  489.                         create = Boolean.FALSE;
  490.                     } else {
  491.                         // There are makeObject() calls in progress that might
  492.                         // bring the pool to capacity. Those calls might also
  493.                         // fail so wait until they complete and then re-test if
  494.                         // the pool is at capacity or not.
  495.                         wait(makeObjectCountLock, remainingWaitDuration);
  496.                     }
  497.                 } else {
  498.                     // The pool is not at capacity. Create a new object.
  499.                     makeObjectCount++;
  500.                     create = Boolean.TRUE;
  501.                 }
  502.             }
  503.             // Do not block more if remainingWaitDuration > 0.
  504.             if (create == null && remainingWaitDuration.compareTo(Duration.ZERO) > 0 &&
  505.                     durationSince(localStartInstant).compareTo(remainingWaitDuration) >= 0) {
  506.                 create = Boolean.FALSE;
  507.             }
  508.         }

  509.         if (!create.booleanValue()) {
  510.             return null;
  511.         }

  512.         final PooledObject<T> p;
  513.         try {
  514.             p = factory.makeObject();
  515.             if (PooledObject.isNull(p)) {
  516.                 createCount.decrementAndGet();
  517.                 throw new NullPointerException(String.format("%s.makeObject() = null", factory.getClass().getSimpleName()));
  518.             }
  519.             if (getTestOnCreate() && !factory.validateObject(p)) {
  520.                 createCount.decrementAndGet();
  521.                 return null;
  522.             }
  523.         } catch (final Throwable e) {
  524.             createCount.decrementAndGet();
  525.             throw e;
  526.         } finally {
  527.             synchronized (makeObjectCountLock) {
  528.                 makeObjectCount--;
  529.                 makeObjectCountLock.notifyAll();
  530.             }
  531.         }

  532.         final AbandonedConfig ac = this.abandonedConfig;
  533.         if (ac != null && ac.getLogAbandoned()) {
  534.             p.setLogAbandoned(true);
  535.             p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
  536.         }

  537.         createdCount.incrementAndGet();
  538.         allObjects.put(new IdentityWrapper<>(p.getObject()), p);
  539.         return p;
  540.     }

  541.     /**
  542.      * Destroys a wrapped pooled object.
  543.      *
  544.      * @param toDestroy The wrapped pooled object to destroy
  545.      * @param destroyMode DestroyMode context provided to the factory
  546.      * @throws Exception If the factory fails to destroy the pooled object
  547.      *                   cleanly
  548.      */
  549.     private void destroy(final PooledObject<T> toDestroy, final DestroyMode destroyMode) throws Exception {
  550.         toDestroy.invalidate();
  551.         idleObjects.remove(toDestroy);
  552.         allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
  553.         try {
  554.             factory.destroyObject(toDestroy, destroyMode);
  555.         } finally {
  556.             destroyedCount.incrementAndGet();
  557.             createCount.decrementAndGet();
  558.         }
  559.     }

  560.     private Duration durationSince(final Instant startInstant) {
  561.         return Duration.between(startInstant, Instant.now());
  562.     }

  563.     /**
  564.      * Tries to ensure that {@code idleCount} idle instances exist in the pool.
  565.      * <p>
  566.      * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
  567.      * or the total number of objects (idle, checked out, or being created) reaches
  568.      * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
  569.      * there are threads waiting to check out instances from the pool.
  570.      * </p>
  571.      * <p>
  572.      * If the factory returns null when creating an instance, a {@code NullPointerException}
  573.      * is thrown.
  574.      * </p>
  575.      *
  576.      * @param idleCount the number of idle instances desired
  577.      * @param always true means create instances even if the pool has no threads waiting
  578.      * @throws Exception if the factory's makeObject throws
  579.      */
  580.     private void ensureIdle(final int idleCount, final boolean always) throws Exception {
  581.         if (idleCount < 1 || isClosed() || !always && !idleObjects.hasTakeWaiters()) {
  582.             return;
  583.         }

  584.         while (idleObjects.size() < idleCount) {
  585.             final PooledObject<T> p = create(getMaxWaitDuration());
  586.             if (PooledObject.isNull(p)) {
  587.                 // Can't create objects, no reason to think another call to
  588.                 // create will work. Give up.
  589.                 break;
  590.             }
  591.             if (getLifo()) {
  592.                 idleObjects.addFirst(p);
  593.             } else {
  594.                 idleObjects.addLast(p);
  595.             }
  596.         }
  597.         if (isClosed()) {
  598.             // Pool closed while object was being added to idle objects.
  599.             // Make sure the returned object is destroyed rather than left
  600.             // in the idle object pool (which would effectively be a leak)
  601.             clear();
  602.         }
  603.     }

  604.     @Override
  605.     void ensureMinIdle() throws Exception {
  606.         ensureIdle(getMinIdle(), true);
  607.     }

  608.     /**
  609.      * {@inheritDoc}
  610.      * <p>
  611.      * Successive activations of this method examine objects in sequence,
  612.      * cycling through objects in oldest-to-youngest order.
  613.      * </p>
  614.      */
  615.     @Override
  616.     public void evict() throws Exception {
  617.         assertOpen();

  618.         if (!idleObjects.isEmpty()) {

  619.             PooledObject<T> underTest = null;
  620.             final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();

  621.             synchronized (evictionLock) {
  622.                 final EvictionConfig evictionConfig = new EvictionConfig(
  623.                         getMinEvictableIdleDuration(),
  624.                         getSoftMinEvictableIdleDuration(),
  625.                         getMinIdle());

  626.                 final boolean testWhileIdle = getTestWhileIdle();

  627.                 for (int i = 0, m = getNumTests(); i < m; i++) {
  628.                     if (evictionIterator == null || !evictionIterator.hasNext()) {
  629.                         evictionIterator = new EvictionIterator(idleObjects);
  630.                     }
  631.                     if (!evictionIterator.hasNext()) {
  632.                         // Pool exhausted, nothing to do here
  633.                         return;
  634.                     }

  635.                     try {
  636.                         underTest = evictionIterator.next();
  637.                     } catch (final NoSuchElementException nsee) {
  638.                         // Object was borrowed in another thread
  639.                         // Don't count this as an eviction test so reduce i;
  640.                         i--;
  641.                         evictionIterator = null;
  642.                         continue;
  643.                     }

  644.                     if (!underTest.startEvictionTest()) {
  645.                         // Object was borrowed in another thread
  646.                         // Don't count this as an eviction test so reduce i;
  647.                         i--;
  648.                         continue;
  649.                     }

  650.                     // User provided eviction policy could throw all sorts of
  651.                     // crazy exceptions. Protect against such an exception
  652.                     // killing the eviction thread.
  653.                     boolean evict;
  654.                     try {
  655.                         evict = evictionPolicy.evict(evictionConfig, underTest,
  656.                                 idleObjects.size());
  657.                     } catch (final Throwable t) {
  658.                         // Slightly convoluted as SwallowedExceptionListener
  659.                         // uses Exception rather than Throwable
  660.                         PoolUtils.checkRethrow(t);
  661.                         swallowException(new Exception(t));
  662.                         // Don't evict on error conditions
  663.                         evict = false;
  664.                     }

  665.                     if (evict) {
  666.                         destroy(underTest, DestroyMode.NORMAL);
  667.                         destroyedByEvictorCount.incrementAndGet();
  668.                     } else {
  669.                         if (testWhileIdle) {
  670.                             boolean active = false;
  671.                             try {
  672.                                 factory.activateObject(underTest);
  673.                                 active = true;
  674.                             } catch (final Exception e) {
  675.                                 destroy(underTest, DestroyMode.NORMAL);
  676.                                 destroyedByEvictorCount.incrementAndGet();
  677.                             }
  678.                             if (active) {
  679.                                 boolean validate = false;
  680.                                 Throwable validationThrowable = null;
  681.                                 try {
  682.                                     validate = factory.validateObject(underTest);
  683.                                 } catch (final Throwable t) {
  684.                                     PoolUtils.checkRethrow(t);
  685.                                     validationThrowable = t;
  686.                                 }
  687.                                 if (!validate) {
  688.                                     destroy(underTest, DestroyMode.NORMAL);
  689.                                     destroyedByEvictorCount.incrementAndGet();
  690.                                     if (validationThrowable != null) {
  691.                                         if (validationThrowable instanceof RuntimeException) {
  692.                                             throw (RuntimeException) validationThrowable;
  693.                                         }
  694.                                         throw (Error) validationThrowable;
  695.                                     }
  696.                                 } else {
  697.                                     try {
  698.                                         factory.passivateObject(underTest);
  699.                                     } catch (final Exception e) {
  700.                                         destroy(underTest, DestroyMode.NORMAL);
  701.                                         destroyedByEvictorCount.incrementAndGet();
  702.                                     }
  703.                                 }
  704.                             }
  705.                         }
  706.                         underTest.endEvictionTest(idleObjects);
  707.                         // TODO - May need to add code here once additional
  708.                         // states are used
  709.                     }
  710.                 }
  711.             }
  712.         }
  713.         final AbandonedConfig ac = this.abandonedConfig;
  714.         if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
  715.             removeAbandoned(ac);
  716.         }
  717.     }

  718.     /**
  719.      * Gets a reference to the factory used to create, destroy and validate
  720.      * the objects used by this pool.
  721.      *
  722.      * @return the factory
  723.      */
  724.     public PooledObjectFactory<T> getFactory() {
  725.         return factory;
  726.     }

  727.     /**
  728.      * Gets the type - including the specific type rather than the generic -
  729.      * of the factory.
  730.      *
  731.      * @return A string representation of the factory type
  732.      */
  733.     @Override
  734.     public String getFactoryType() {
  735.         // Not thread safe. Accept that there may be multiple evaluations.
  736.         if (factoryType == null) {
  737.             final StringBuilder result = new StringBuilder();
  738.             result.append(factory.getClass().getName());
  739.             result.append('<');
  740.             final Class<?> pooledObjectType =
  741.                     PoolImplUtils.getFactoryType(factory.getClass());
  742.             result.append(pooledObjectType.getName());
  743.             result.append('>');
  744.             factoryType = result.toString();
  745.         }
  746.         return factoryType;
  747.     }

  748.     /**
  749.      * Gets the cap on the number of "idle" instances in the pool. If maxIdle
  750.      * is set too low on heavily loaded systems it is possible you will see
  751.      * objects being destroyed and almost immediately new objects being created.
  752.      * This is a result of the active threads momentarily returning objects
  753.      * faster than they are requesting them, causing the number of idle
  754.      * objects to rise above maxIdle. The best value for maxIdle for heavily
  755.      * loaded system will vary but the default is a good starting point.
  756.      *
  757.      * @return the maximum number of "idle" instances that can be held in the
  758.      *         pool or a negative value if there is no limit
  759.      * @see #setMaxIdle
  760.      */
  761.     @Override
  762.     public int getMaxIdle() {
  763.         return maxIdle;
  764.     }

  765.     /**
  766.      * Gets the target for the minimum number of idle objects to maintain in
  767.      * the pool. This setting only has an effect if it is positive and
  768.      * {@link #getDurationBetweenEvictionRuns()} is greater than zero. If this
  769.      * is the case, an attempt is made to ensure that the pool has the required
  770.      * minimum number of instances during idle object eviction runs.
  771.      * <p>
  772.      * If the configured value of minIdle is greater than the configured value
  773.      * for maxIdle then the value of maxIdle will be used instead.
  774.      * </p>
  775.      *
  776.      * @return The minimum number of objects.
  777.      * @see #setMinIdle(int)
  778.      * @see #setMaxIdle(int)
  779.      * @see #setDurationBetweenEvictionRuns(Duration)
  780.      */
  781.     @Override
  782.     public int getMinIdle() {
  783.         final int maxIdleSave = getMaxIdle();
  784.         return Math.min(this.minIdle, maxIdleSave);
  785.     }

  786.     @Override
  787.     public int getNumActive() {
  788.         return allObjects.size() - idleObjects.size();
  789.     }

  790.     @Override
  791.     public int getNumIdle() {
  792.         return idleObjects.size();
  793.     }

  794.     /**
  795.      * Calculates the number of objects to test in a run of the idle object
  796.      * evictor.
  797.      *
  798.      * @return The number of objects to test for validity
  799.      */
  800.     private int getNumTests() {
  801.         final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
  802.         if (numTestsPerEvictionRun >= 0) {
  803.             return Math.min(numTestsPerEvictionRun, idleObjects.size());
  804.         }
  805.         return (int) Math.ceil(idleObjects.size() /
  806.                 Math.abs((double) numTestsPerEvictionRun));
  807.     }

  808.     /**
  809.      * Gets an estimate of the number of threads currently blocked waiting for
  810.      * an object from the pool. This is intended for monitoring only, not for
  811.      * synchronization control.
  812.      *
  813.      * @return The estimate of the number of threads currently blocked waiting
  814.      *         for an object from the pool
  815.      */
  816.     @Override
  817.     public int getNumWaiters() {
  818.         if (getBlockWhenExhausted()) {
  819.             return idleObjects.getTakeQueueLength();
  820.         }
  821.         return 0;
  822.     }

  823.     PooledObject<T> getPooledObject(final T obj) {
  824.         return allObjects.get(new IdentityWrapper<>(obj));
  825.     }

  826.     @Override
  827.     String getStatsString() {
  828.         // Simply listed in AB order.
  829.         return super.getStatsString() +
  830.                 String.format(", createdCount=%,d, makeObjectCount=%,d, maxIdle=%,d, minIdle=%,d",
  831.                         createdCount.get(), makeObjectCount, maxIdle, minIdle);
  832.     }

  833.     /**
  834.      * {@inheritDoc}
  835.      * <p>
  836.      * Activation of this method decrements the active count and attempts to destroy the instance, using the default
  837.      * (NORMAL) {@link DestroyMode}.
  838.      * </p>
  839.      *
  840.      * @throws Exception if an exception occurs destroying the
  841.      * @throws IllegalStateException if obj does not belong to this pool
  842.      */
  843.     @Override
  844.     public void invalidateObject(final T obj) throws Exception {
  845.         invalidateObject(obj, DestroyMode.NORMAL);
  846.     }

  847.     /**
  848.      * {@inheritDoc}
  849.      * <p>
  850.      * Activation of this method decrements the active count and attempts to destroy the instance, using the provided
  851.      * {@link DestroyMode}.
  852.      * </p>
  853.      *
  854.      * @throws Exception if an exception occurs destroying the object
  855.      * @throws IllegalStateException if obj does not belong to this pool
  856.      * @since 2.9.0
  857.      */
  858.     @Override
  859.     public void invalidateObject(final T obj, final DestroyMode destroyMode) throws Exception {
  860.         final PooledObject<T> p = getPooledObject(obj);
  861.         if (p == null) {
  862.             if (isAbandonedConfig()) {
  863.                 return;
  864.             }
  865.             throw new IllegalStateException("Invalidated object not currently part of this pool");
  866.         }
  867.         synchronized (p) {
  868.             if (p.getState() != PooledObjectState.INVALID) {
  869.                 destroy(p, destroyMode);
  870.             }
  871.         }
  872.         ensureIdle(1, false);
  873.     }

  874.     /**
  875.      * Provides information on all the objects in the pool, both idle (waiting
  876.      * to be borrowed) and active (currently borrowed).
  877.      * <p>
  878.      * Note: This is named listAllObjects so it is presented as an operation via
  879.      * JMX. That means it won't be invoked unless the explicitly requested
  880.      * whereas all attributes will be automatically requested when viewing the
  881.      * attributes for an object in a tool like JConsole.
  882.      * </p>
  883.      *
  884.      * @return Information grouped on all the objects in the pool
  885.      */
  886.     @Override
  887.     public Set<DefaultPooledObjectInfo> listAllObjects() {
  888.         return allObjects.values().stream().map(DefaultPooledObjectInfo::new).collect(Collectors.toSet());
  889.     }
  890.     /**
  891.      * Tries to ensure that {@link #getMinIdle()} idle instances are available
  892.      * in the pool.
  893.      *
  894.      * @throws Exception If the associated factory throws an exception
  895.      * @since 2.4
  896.      */
  897.     public void preparePool() throws Exception {
  898.         if (getMinIdle() < 1) {
  899.             return;
  900.         }
  901.         ensureMinIdle();
  902.     }

  903.     /**
  904.      * Recovers abandoned objects which have been checked out but
  905.      * not used since longer than the removeAbandonedTimeout.
  906.      *
  907.      * @param abandonedConfig The configuration to use to identify abandoned objects
  908.      */
  909.     @SuppressWarnings("resource") // PrintWriter is managed elsewhere
  910.     private void removeAbandoned(final AbandonedConfig abandonedConfig) {
  911.         // Generate a list of abandoned objects to remove
  912.         final ArrayList<PooledObject<T>> remove = createRemoveList(abandonedConfig, allObjects);
  913.         // Now remove the abandoned objects
  914.         remove.forEach(pooledObject -> {
  915.             if (abandonedConfig.getLogAbandoned()) {
  916.                 pooledObject.printStackTrace(abandonedConfig.getLogWriter());
  917.             }
  918.             try {
  919.                 invalidateObject(pooledObject.getObject(), DestroyMode.ABANDONED);
  920.             } catch (final Exception e) {
  921.                 swallowException(e);
  922.             }
  923.         });
  924.     }

  925.     /**
  926.      * {@inheritDoc}
  927.      * <p>
  928.      * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
  929.      * number of idle instances has reached this value, the returning instance
  930.      * is destroyed.
  931.      * </p>
  932.      * <p>
  933.      * If {@link #getTestOnReturn() testOnReturn} == true, the returning
  934.      * instance is validated before being returned to the idle instance pool. In
  935.      * this case, if validation fails, the instance is destroyed.
  936.      * </p>
  937.      * <p>
  938.      * Exceptions encountered destroying objects for any reason are swallowed
  939.      * but notified via a {@link SwallowedExceptionListener}.
  940.      * </p>
  941.      */
  942.     @Override
  943.     public void returnObject(final T obj) {
  944.         final PooledObject<T> p = getPooledObject(obj);

  945.         if (p == null) {
  946.             if (!isAbandonedConfig()) {
  947.                 throw new IllegalStateException(
  948.                         "Returned object not currently part of this pool");
  949.             }
  950.             return; // Object was abandoned and removed
  951.         }

  952.         markReturningState(p);

  953.         final Duration activeTime = p.getActiveDuration();

  954.         if (getTestOnReturn() && !factory.validateObject(p)) {
  955.             try {
  956.                 destroy(p, DestroyMode.NORMAL);
  957.             } catch (final Exception e) {
  958.                 swallowException(e);
  959.             }
  960.             try {
  961.                 ensureIdle(1, false);
  962.             } catch (final Exception e) {
  963.                 swallowException(e);
  964.             }
  965.             updateStatsReturn(activeTime);
  966.             return;
  967.         }

  968.         try {
  969.             factory.passivateObject(p);
  970.         } catch (final Exception e1) {
  971.             swallowException(e1);
  972.             try {
  973.                 destroy(p, DestroyMode.NORMAL);
  974.             } catch (final Exception e) {
  975.                 swallowException(e);
  976.             }
  977.             try {
  978.                 ensureIdle(1, false);
  979.             } catch (final Exception e) {
  980.                 swallowException(e);
  981.             }
  982.             updateStatsReturn(activeTime);
  983.             return;
  984.         }

  985.         if (!p.deallocate()) {
  986.             throw new IllegalStateException(
  987.                     "Object has already been returned to this pool or is invalid");
  988.         }

  989.         final int maxIdleSave = getMaxIdle();
  990.         if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
  991.             try {
  992.                 destroy(p, DestroyMode.NORMAL);
  993.             } catch (final Exception e) {
  994.                 swallowException(e);
  995.             }
  996.             try {
  997.                 ensureIdle(1, false);
  998.             } catch (final Exception e) {
  999.                 swallowException(e);
  1000.             }
  1001.         } else {
  1002.             if (getLifo()) {
  1003.                 idleObjects.addFirst(p);
  1004.             } else {
  1005.                 idleObjects.addLast(p);
  1006.             }
  1007.             if (isClosed()) {
  1008.                 // Pool closed while object was being added to idle objects.
  1009.                 // Make sure the returned object is destroyed rather than left
  1010.                 // in the idle object pool (which would effectively be a leak)
  1011.                 clear();
  1012.             }
  1013.         }
  1014.         updateStatsReturn(activeTime);
  1015.     }

  1016.     /**
  1017.      * Sets the base pool configuration.
  1018.      *
  1019.      * @param conf the new configuration to use. This is used by value.
  1020.      * @see GenericObjectPoolConfig
  1021.      */
  1022.     public void setConfig(final GenericObjectPoolConfig<T> conf) {
  1023.         super.setConfig(conf);
  1024.         setMaxIdle(conf.getMaxIdle());
  1025.         setMinIdle(conf.getMinIdle());
  1026.         setMaxTotal(conf.getMaxTotal());
  1027.     }

  1028.     /**
  1029.      * Sets the cap on the number of "idle" instances in the pool. If maxIdle
  1030.      * is set too low on heavily loaded systems it is possible you will see
  1031.      * objects being destroyed and almost immediately new objects being created.
  1032.      * This is a result of the active threads momentarily returning objects
  1033.      * faster than they are requesting them, causing the number of idle
  1034.      * objects to rise above maxIdle. The best value for maxIdle for heavily
  1035.      * loaded system will vary but the default is a good starting point.
  1036.      *
  1037.      * @param maxIdle
  1038.      *            The cap on the number of "idle" instances in the pool. Use a
  1039.      *            negative value to indicate an unlimited number of idle
  1040.      *            instances
  1041.      * @see #getMaxIdle
  1042.      */
  1043.     public void setMaxIdle(final int maxIdle) {
  1044.         this.maxIdle = maxIdle;
  1045.     }

  1046.     /**
  1047.      * Sets the target for the minimum number of idle objects to maintain in
  1048.      * the pool. This setting only has an effect if it is positive and
  1049.      * {@link #getDurationBetweenEvictionRuns()} is greater than zero. If this
  1050.      * is the case, an attempt is made to ensure that the pool has the required
  1051.      * minimum number of instances during idle object eviction runs.
  1052.      * <p>
  1053.      * If the configured value of minIdle is greater than the configured value
  1054.      * for maxIdle then the value of maxIdle will be used instead.
  1055.      * </p>
  1056.      *
  1057.      * @param minIdle
  1058.      *            The minimum number of objects.
  1059.      * @see #getMinIdle()
  1060.      * @see #getMaxIdle()
  1061.      * @see #getDurationBetweenEvictionRuns()
  1062.      */
  1063.     public void setMinIdle(final int minIdle) {
  1064.         this.minIdle = minIdle;
  1065.     }

  1066.     @Override
  1067.     protected void toStringAppendFields(final StringBuilder builder) {
  1068.         super.toStringAppendFields(builder);
  1069.         builder.append(", factoryType=");
  1070.         builder.append(factoryType);
  1071.         builder.append(", maxIdle=");
  1072.         builder.append(maxIdle);
  1073.         builder.append(", minIdle=");
  1074.         builder.append(minIdle);
  1075.         builder.append(", factory=");
  1076.         builder.append(factory);
  1077.         builder.append(", allObjects=");
  1078.         builder.append(allObjects);
  1079.         builder.append(", createCount=");
  1080.         builder.append(createCount);
  1081.         builder.append(", idleObjects=");
  1082.         builder.append(idleObjects);
  1083.         builder.append(", abandonedConfig=");
  1084.         builder.append(abandonedConfig);
  1085.     }

  1086.     @Override
  1087.     public void use(final T pooledObject) {
  1088.         final AbandonedConfig abandonedCfg = this.abandonedConfig;
  1089.         if (abandonedCfg != null && abandonedCfg.getUseUsageTracking()) {
  1090.             final PooledObject<T> po = getPooledObject(pooledObject);
  1091.             if (po != null) {
  1092.                 po.use();
  1093.             }
  1094.         }
  1095.     }

  1096. }