001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.pool2.impl;
018
019import java.util.ArrayList;
020import java.util.Deque;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025import java.util.Map.Entry;
026import java.util.NoSuchElementException;
027import java.util.TreeMap;
028import java.util.concurrent.ConcurrentHashMap;
029import java.util.concurrent.TimeUnit;
030import java.util.concurrent.atomic.AtomicInteger;
031import java.util.concurrent.atomic.AtomicLong;
032import java.util.concurrent.locks.Lock;
033import java.util.concurrent.locks.ReadWriteLock;
034import java.util.concurrent.locks.ReentrantReadWriteLock;
035
036import org.apache.commons.pool2.KeyedObjectPool;
037import org.apache.commons.pool2.KeyedPooledObjectFactory;
038import org.apache.commons.pool2.PoolUtils;
039import org.apache.commons.pool2.PooledObject;
040import org.apache.commons.pool2.PooledObjectState;
041import org.apache.commons.pool2.SwallowedExceptionListener;
042
043/**
044 * A configurable <code>KeyedObjectPool</code> implementation.
045 * <p>
046 * When coupled with the appropriate {@link KeyedPooledObjectFactory},
047 * <code>GenericKeyedObjectPool</code> provides robust pooling functionality for
048 * keyed objects. A <code>GenericKeyedObjectPool</code> can be viewed as a map
049 * of sub-pools, keyed on the (unique) key values provided to the
050 * {@link #preparePool preparePool}, {@link #addObject addObject} or
051 * {@link #borrowObject borrowObject} methods. Each time a new key value is
052 * provided to one of these methods, a sub-new pool is created under the given
053 * key to be managed by the containing <code>GenericKeyedObjectPool.</code>
054 * <p>
055 * Note that the current implementation uses a ConcurrentHashMap which uses
056 * equals() to compare keys.
057 * This means that distinct instance keys must be distinguishable using equals.
058 * <p>
059 * Optionally, one may configure the pool to examine and possibly evict objects
060 * as they sit idle in the pool and to ensure that a minimum number of idle
061 * objects is maintained for each key. This is performed by an "idle object
062 * eviction" thread, which runs asynchronously. Caution should be used when
063 * configuring this optional feature. Eviction runs contend with client threads
064 * for access to objects in the pool, so if they run too frequently performance
065 * issues may result.
066 * <p>
067 * Implementation note: To prevent possible deadlocks, care has been taken to
068 * ensure that no call to a factory method will occur within a synchronization
069 * block. See POOL-125 and DBCP-44 for more information.
070 * <p>
071 * This class is intended to be thread-safe.
072 *
073 * @see GenericObjectPool
074 *
075 * @param <K> The type of keys maintained by this pool.
076 * @param <T> Type of element pooled in this pool.
077 *
078 * @since 2.0
079 */
080public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T>
081        implements KeyedObjectPool<K, T>, GenericKeyedObjectPoolMXBean<K> {
082
083    /**
084     * Create a new <code>GenericKeyedObjectPool</code> using defaults from
085     * {@link GenericKeyedObjectPoolConfig}.
086     * @param factory the factory to be used to create entries
087     */
088    public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K,T> factory) {
089        this(factory, new GenericKeyedObjectPoolConfig<T>());
090    }
091
092    /**
093     * Create a new <code>GenericKeyedObjectPool</code> using a specific
094     * configuration.
095     *
096     * @param factory the factory to be used to create entries
097     * @param config    The configuration to use for this pool instance. The
098     *                  configuration is used by value. Subsequent changes to
099     *                  the configuration object will not be reflected in the
100     *                  pool.
101     */
102    public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K, T> factory,
103            final GenericKeyedObjectPoolConfig<T> config) {
104
105        super(config, ONAME_BASE, config.getJmxNamePrefix());
106
107        if (factory == null) {
108            jmxUnregister(); // tidy up
109            throw new IllegalArgumentException("factory may not be null");
110        }
111        this.factory = factory;
112        this.fairness = config.getFairness();
113
114        setConfig(config);
115    }
116
117    /**
118     * Returns the limit on the number of object instances allocated by the pool
119     * (checked out or idle), per key. When the limit is reached, the sub-pool
120     * is said to be exhausted. A negative value indicates no limit.
121     *
122     * @return the limit on the number of active instances per key
123     *
124     * @see #setMaxTotalPerKey
125     */
126    @Override
127    public int getMaxTotalPerKey() {
128        return maxTotalPerKey;
129    }
130
131    /**
132     * Sets the limit on the number of object instances allocated by the pool
133     * (checked out or idle), per key. When the limit is reached, the sub-pool
134     * is said to be exhausted. A negative value indicates no limit.
135     *
136     * @param maxTotalPerKey the limit on the number of active instances per key
137     *
138     * @see #getMaxTotalPerKey
139     */
140    public void setMaxTotalPerKey(final int maxTotalPerKey) {
141        this.maxTotalPerKey = maxTotalPerKey;
142    }
143
144
145    /**
146     * Returns the cap on the number of "idle" instances per key in the pool.
147     * If maxIdlePerKey is set too low on heavily loaded systems it is possible
148     * you will see objects being destroyed and almost immediately new objects
149     * being created. This is a result of the active threads momentarily
150     * returning objects faster than they are requesting them, causing the
151     * number of idle objects to rise above maxIdlePerKey. The best value for
152     * maxIdlePerKey for heavily loaded system will vary but the default is a
153     * good starting point.
154     *
155     * @return the maximum number of "idle" instances that can be held in a
156     *         given keyed sub-pool or a negative value if there is no limit
157     *
158     * @see #setMaxIdlePerKey
159     */
160    @Override
161    public int getMaxIdlePerKey() {
162        return maxIdlePerKey;
163    }
164
165    /**
166     * Sets the cap on the number of "idle" instances per key in the pool.
167     * If maxIdlePerKey is set too low on heavily loaded systems it is possible
168     * you will see objects being destroyed and almost immediately new objects
169     * being created. This is a result of the active threads momentarily
170     * returning objects faster than they are requesting them, causing the
171     * number of idle objects to rise above maxIdlePerKey. The best value for
172     * maxIdlePerKey for heavily loaded system will vary but the default is a
173     * good starting point.
174     *
175     * @param maxIdlePerKey the maximum number of "idle" instances that can be
176     *                      held in a given keyed sub-pool. Use a negative value
177     *                      for no limit
178     *
179     * @see #getMaxIdlePerKey
180     */
181    public void setMaxIdlePerKey(final int maxIdlePerKey) {
182        this.maxIdlePerKey = maxIdlePerKey;
183    }
184
185    /**
186     * Sets the target for the minimum number of idle objects to maintain in
187     * each of the keyed sub-pools. This setting only has an effect if it is
188     * positive and {@link #getTimeBetweenEvictionRunsMillis()} is greater than
189     * zero. If this is the case, an attempt is made to ensure that each
190     * sub-pool has the required minimum number of instances during idle object
191     * eviction runs.
192     * <p>
193     * If the configured value of minIdlePerKey is greater than the configured
194     * value for maxIdlePerKey then the value of maxIdlePerKey will be used
195     * instead.
196     *
197     * @param minIdlePerKey The minimum size of the each keyed pool
198     *
199     * @see #getMinIdlePerKey
200     * @see #getMaxIdlePerKey()
201     * @see #setTimeBetweenEvictionRunsMillis
202     */
203    public void setMinIdlePerKey(final int minIdlePerKey) {
204        this.minIdlePerKey = minIdlePerKey;
205    }
206
207    /**
208     * Returns the target for the minimum number of idle objects to maintain in
209     * each of the keyed sub-pools. This setting only has an effect if it is
210     * positive and {@link #getTimeBetweenEvictionRunsMillis()} is greater than
211     * zero. If this is the case, an attempt is made to ensure that each
212     * sub-pool has the required minimum number of instances during idle object
213     * eviction runs.
214     * <p>
215     * If the configured value of minIdlePerKey is greater than the configured
216     * value for maxIdlePerKey then the value of maxIdlePerKey will be used
217     * instead.
218     *
219     * @return minimum size of the each keyed pool
220     *
221     * @see #setTimeBetweenEvictionRunsMillis
222     */
223    @Override
224    public int getMinIdlePerKey() {
225        final int maxIdlePerKeySave = getMaxIdlePerKey();
226        if (this.minIdlePerKey > maxIdlePerKeySave) {
227            return maxIdlePerKeySave;
228        }
229        return minIdlePerKey;
230    }
231
232    /**
233     * Sets the configuration.
234     *
235     * @param conf the new configuration to use. This is used by value.
236     *
237     * @see GenericKeyedObjectPoolConfig
238     */
239    public void setConfig(final GenericKeyedObjectPoolConfig<T> conf) {
240        setLifo(conf.getLifo());
241        setMaxIdlePerKey(conf.getMaxIdlePerKey());
242        setMaxTotalPerKey(conf.getMaxTotalPerKey());
243        setMaxTotal(conf.getMaxTotal());
244        setMinIdlePerKey(conf.getMinIdlePerKey());
245        setMaxWaitMillis(conf.getMaxWaitMillis());
246        setBlockWhenExhausted(conf.getBlockWhenExhausted());
247        setTestOnCreate(conf.getTestOnCreate());
248        setTestOnBorrow(conf.getTestOnBorrow());
249        setTestOnReturn(conf.getTestOnReturn());
250        setTestWhileIdle(conf.getTestWhileIdle());
251        setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun());
252        setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis());
253        setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis());
254        setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis());
255        final EvictionPolicy<T> policy = conf.getEvictionPolicy();
256        if (policy == null) {
257            // Use the class name (pre-2.6.0 compatible)
258            setEvictionPolicyClassName(conf.getEvictionPolicyClassName());
259        } else {
260            // Otherwise, use the class (2.6.0 feature)
261            setEvictionPolicy(policy);
262        }
263        setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis());
264    }
265
266    /**
267     * Obtain a reference to the factory used to create, destroy and validate
268     * the objects used by this pool.
269     *
270     * @return the factory
271     */
272    public KeyedPooledObjectFactory<K, T> getFactory() {
273        return factory;
274    }
275
276    /**
277     * Equivalent to <code>{@link #borrowObject(Object, long) borrowObject}(key,
278     * {@link #getMaxWaitMillis()})</code>.
279     * <p>
280     * {@inheritDoc}
281     */
282    @Override
283    public T borrowObject(final K key) throws Exception {
284        return borrowObject(key, getMaxWaitMillis());
285    }
286
287    /**
288     * Borrows an object from the sub-pool associated with the given key using
289     * the specified waiting time which only applies if
290     * {@link #getBlockWhenExhausted()} is true.
291     * <p>
292     * If there is one or more idle instances available in the sub-pool
293     * associated with the given key, then an idle instance will be selected
294     * based on the value of {@link #getLifo()}, activated and returned.  If
295     * activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set to
296     * <code>true</code> and validation fails, the instance is destroyed and the
297     * next available instance is examined.  This continues until either a valid
298     * instance is returned or there are no more idle instances available.
299     * <p>
300     * If there are no idle instances available in the sub-pool associated with
301     * the given key, behavior depends on the {@link #getMaxTotalPerKey()
302     * maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable)
303     * {@link #getBlockWhenExhausted()} and the value passed in to the
304     * <code>borrowMaxWaitMillis</code> parameter. If the number of instances checked
305     * out from the sub-pool under the given key is less than
306     * <code>maxTotalPerKey</code> and the total number of instances in
307     * circulation (under all keys) is less than <code>maxTotal</code>, a new
308     * instance is created, activated and (if applicable) validated and returned
309     * to the caller. If validation fails, a <code>NoSuchElementException</code>
310     * will be thrown.
311     * <p>
312     * If the associated sub-pool is exhausted (no available idle instances and
313     * no capacity to create new ones), this method will either block
314     * ({@link #getBlockWhenExhausted()} is true) or throw a
315     * <code>NoSuchElementException</code>
316     * ({@link #getBlockWhenExhausted()} is false).
317     * The length of time that this method will block when
318     * {@link #getBlockWhenExhausted()} is true is determined by the value
319     * passed in to the <code>borrowMaxWait</code> parameter.
320     * <p>
321     * When <code>maxTotal</code> is set to a positive value and this method is
322     * invoked when at the limit with no idle instances available under the requested
323     * key, an attempt is made to create room by clearing the oldest 15% of the
324     * elements from the keyed sub-pools.
325     * <p>
326     * When the pool is exhausted, multiple calling threads may be
327     * simultaneously blocked waiting for instances to become available. A
328     * "fairness" algorithm has been implemented to ensure that threads receive
329     * available instances in request arrival order.
330     *
331     * @param key pool key
332     * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
333     *                            to become available
334     *
335     * @return object instance from the keyed pool
336     *
337     * @throws NoSuchElementException if a keyed object instance cannot be
338     *                                returned because the pool is exhausted.
339     *
340     * @throws Exception if a keyed object instance cannot be returned due to an
341     *                   error
342     */
343    public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception {
344        assertOpen();
345
346        PooledObject<T> p = null;
347
348        // Get local copy of current config so it is consistent for entire
349        // method execution
350        final boolean blockWhenExhausted = getBlockWhenExhausted();
351
352        boolean create;
353        final long waitTime = System.currentTimeMillis();
354        final ObjectDeque<T> objectDeque = register(key);
355
356        try {
357            while (p == null) {
358                create = false;
359                p = objectDeque.getIdleObjects().pollFirst();
360                if (p == null) {
361                    p = create(key);
362                    if (p != null) {
363                        create = true;
364                    }
365                }
366                if (blockWhenExhausted) {
367                    if (p == null) {
368                        if (borrowMaxWaitMillis < 0) {
369                            p = objectDeque.getIdleObjects().takeFirst();
370                        } else {
371                            p = objectDeque.getIdleObjects().pollFirst(
372                                    borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
373                        }
374                    }
375                    if (p == null) {
376                        throw new NoSuchElementException(
377                                "Timeout waiting for idle object");
378                    }
379                } else {
380                    if (p == null) {
381                        throw new NoSuchElementException("Pool exhausted");
382                    }
383                }
384                if (!p.allocate()) {
385                    p = null;
386                }
387
388                if (p != null) {
389                    try {
390                        factory.activateObject(key, p);
391                    } catch (final Exception e) {
392                        try {
393                            destroy(key, p, true);
394                        } catch (final Exception e1) {
395                            // Ignore - activation failure is more important
396                        }
397                        p = null;
398                        if (create) {
399                            final NoSuchElementException nsee = new NoSuchElementException(
400                                    "Unable to activate object");
401                            nsee.initCause(e);
402                            throw nsee;
403                        }
404                    }
405                    if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
406                        boolean validate = false;
407                        Throwable validationThrowable = null;
408                        try {
409                            validate = factory.validateObject(key, p);
410                        } catch (final Throwable t) {
411                            PoolUtils.checkRethrow(t);
412                            validationThrowable = t;
413                        }
414                        if (!validate) {
415                            try {
416                                destroy(key, p, true);
417                                destroyedByBorrowValidationCount.incrementAndGet();
418                            } catch (final Exception e) {
419                                // Ignore - validation failure is more important
420                            }
421                            p = null;
422                            if (create) {
423                                final NoSuchElementException nsee = new NoSuchElementException(
424                                        "Unable to validate object");
425                                nsee.initCause(validationThrowable);
426                                throw nsee;
427                            }
428                        }
429                    }
430                }
431            }
432        } finally {
433            deregister(key);
434        }
435
436        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
437
438        return p.getObject();
439    }
440
441
442    /**
443     * Returns an object to a keyed sub-pool.
444     * <p>
445     * If {@link #getMaxIdlePerKey() maxIdle} is set to a positive value and the
446     * number of idle instances under the given key has reached this value, the
447     * returning instance is destroyed.
448     * <p>
449     * If {@link #getTestOnReturn() testOnReturn} == true, the returning
450     * instance is validated before being returned to the idle instance sub-pool
451     * under the given key. In this case, if validation fails, the instance is
452     * destroyed.
453     * <p>
454     * Exceptions encountered destroying objects for any reason are swallowed
455     * but notified via a {@link SwallowedExceptionListener}.
456     *
457     * @param key pool key
458     * @param obj instance to return to the keyed pool
459     *
460     * @throws IllegalStateException if an object is returned to the pool that
461     *                               was not borrowed from it or if an object is
462     *                               returned to the pool multiple times
463     */
464    @Override
465    public void returnObject(final K key, final T obj) {
466
467        final ObjectDeque<T> objectDeque = poolMap.get(key);
468
469        final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
470
471        if (p == null) {
472            throw new IllegalStateException(
473                    "Returned object not currently part of this pool");
474        }
475
476        markReturningState(p);
477
478        final long activeTime = p.getActiveTimeMillis();
479
480        try {
481            if (getTestOnReturn() && !factory.validateObject(key, p)) {
482                try {
483                    destroy(key, p, true);
484                } catch (final Exception e) {
485                    swallowException(e);
486                }
487                whenWaitersAddObject(key, objectDeque.idleObjects);
488                return;
489            }
490
491            try {
492                factory.passivateObject(key, p);
493            } catch (final Exception e1) {
494                swallowException(e1);
495                try {
496                    destroy(key, p, true);
497                } catch (final Exception e) {
498                    swallowException(e);
499                }
500                whenWaitersAddObject(key, objectDeque.idleObjects);
501                return;
502            }
503
504            if (!p.deallocate()) {
505                throw new IllegalStateException(
506                        "Object has already been returned to this pool");
507            }
508
509            final int maxIdle = getMaxIdlePerKey();
510            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
511                    objectDeque.getIdleObjects();
512
513            if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
514                try {
515                    destroy(key, p, true);
516                } catch (final Exception e) {
517                    swallowException(e);
518                }
519            } else {
520                if (getLifo()) {
521                    idleObjects.addFirst(p);
522                } else {
523                    idleObjects.addLast(p);
524                }
525                if (isClosed()) {
526                    // Pool closed while object was being added to idle objects.
527                    // Make sure the returned object is destroyed rather than left
528                    // in the idle object pool (which would effectively be a leak)
529                    clear(key);
530                }
531            }
532        } finally {
533            if (hasBorrowWaiters()) {
534                reuseCapacity();
535            }
536            updateStatsReturn(activeTime);
537        }
538    }
539
540    /**
541     * Whether there is at least one thread waiting on this deque, add an pool object.
542     * @param key
543     * @param idleObjects
544     */
545    private void whenWaitersAddObject(final K key, final LinkedBlockingDeque<PooledObject<T>> idleObjects) {
546        if (idleObjects.hasTakeWaiters()) {
547            try {
548                addObject(key);
549            } catch (final Exception e) {
550                swallowException(e);
551            }
552        }
553    }
554
555    /**
556     * {@inheritDoc}
557     * <p>
558     * Activation of this method decrements the active count associated with
559     * the given keyed pool and attempts to destroy <code>obj.</code>
560     *
561     * @param key pool key
562     * @param obj instance to invalidate
563     *
564     * @throws Exception             if an exception occurs destroying the
565     *                               object
566     * @throws IllegalStateException if obj does not belong to the pool
567     *                               under the given key
568     */
569    @Override
570    public void invalidateObject(final K key, final T obj) throws Exception {
571
572        final ObjectDeque<T> objectDeque = poolMap.get(key);
573
574        final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
575        if (p == null) {
576            throw new IllegalStateException(
577                    "Object not currently part of this pool");
578        }
579        synchronized (p) {
580            if (p.getState() != PooledObjectState.INVALID) {
581                destroy(key, p, true);
582            }
583        }
584        if (objectDeque.idleObjects.hasTakeWaiters()) {
585            addObject(key);
586        }
587    }
588
589
590    /**
591     * Clears any objects sitting idle in the pool by removing them from the
592     * idle instance sub-pools and then invoking the configured
593     * PoolableObjectFactory's
594     * {@link KeyedPooledObjectFactory#destroyObject(Object, PooledObject)}
595     * method on each idle instance.
596     * <p>
597     * Implementation notes:
598     * <ul>
599     * <li>This method does not destroy or effect in any way instances that are
600     * checked out when it is invoked.</li>
601     * <li>Invoking this method does not prevent objects being returned to the
602     * idle instance pool, even during its execution. Additional instances may
603     * be returned while removed items are being destroyed.</li>
604     * <li>Exceptions encountered destroying idle instances are swallowed
605     * but notified via a {@link SwallowedExceptionListener}.</li>
606     * </ul>
607     */
608    @Override
609    public void clear() {
610        final Iterator<K> iter = poolMap.keySet().iterator();
611
612        while (iter.hasNext()) {
613            clear(iter.next());
614        }
615    }
616
617
618    /**
619     * Clears the specified sub-pool, removing all pooled instances
620     * corresponding to the given <code>key</code>. Exceptions encountered
621     * destroying idle instances are swallowed but notified via a
622     * {@link SwallowedExceptionListener}.
623     *
624     * @param key the key to clear
625     */
626    @Override
627    public void clear(final K key) {
628
629        final ObjectDeque<T> objectDeque = register(key);
630
631        try {
632            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
633                    objectDeque.getIdleObjects();
634
635            PooledObject<T> p = idleObjects.poll();
636
637            while (p != null) {
638                try {
639                    destroy(key, p, true);
640                } catch (final Exception e) {
641                    swallowException(e);
642                }
643                p = idleObjects.poll();
644            }
645        } finally {
646            deregister(key);
647        }
648    }
649
650
651    @Override
652    public int getNumActive() {
653        return numTotal.get() - getNumIdle();
654    }
655
656
657    @Override
658    public int getNumIdle() {
659        final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
660        int result = 0;
661
662        while (iter.hasNext()) {
663            result += iter.next().getIdleObjects().size();
664        }
665
666        return result;
667    }
668
669
670    @Override
671    public int getNumActive(final K key) {
672        final ObjectDeque<T> objectDeque = poolMap.get(key);
673        if (objectDeque != null) {
674            return objectDeque.getAllObjects().size() -
675                    objectDeque.getIdleObjects().size();
676        }
677        return 0;
678    }
679
680
681    @Override
682    public int getNumIdle(final K key) {
683        final ObjectDeque<T> objectDeque = poolMap.get(key);
684        return objectDeque != null ? objectDeque.getIdleObjects().size() : 0;
685    }
686
687
688    /**
689     * Closes the keyed object pool. Once the pool is closed,
690     * {@link #borrowObject(Object)} will fail with IllegalStateException, but
691     * {@link #returnObject(Object, Object)} and
692     * {@link #invalidateObject(Object, Object)} will continue to work, with
693     * returned objects destroyed on return.
694     * <p>
695     * Destroys idle instances in the pool by invoking {@link #clear()}.
696     */
697    @Override
698    public void close() {
699        if (isClosed()) {
700            return;
701        }
702
703        synchronized (closeLock) {
704            if (isClosed()) {
705                return;
706            }
707
708            // Stop the evictor before the pool is closed since evict() calls
709            // assertOpen()
710            startEvictor(-1L);
711
712            closed = true;
713            // This clear removes any idle objects
714            clear();
715
716            jmxUnregister();
717
718            // Release any threads that were waiting for an object
719            final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
720            while (iter.hasNext()) {
721                iter.next().getIdleObjects().interuptTakeWaiters();
722            }
723            // This clear cleans up the keys now any waiting threads have been
724            // interrupted
725            clear();
726        }
727    }
728
729
730    /**
731     * Clears oldest 15% of objects in pool.  The method sorts the objects into
732     * a TreeMap and then iterates the first 15% for removal.
733     */
734    public void clearOldest() {
735
736        // build sorted map of idle objects
737        final Map<PooledObject<T>, K> map = new TreeMap<>();
738
739        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
740            final K k = entry.getKey();
741            final ObjectDeque<T> deque = entry.getValue();
742            // Protect against possible NPE if key has been removed in another
743            // thread. Not worth locking the keys while this loop completes.
744            if (deque != null) {
745                final LinkedBlockingDeque<PooledObject<T>> idleObjects =
746                        deque.getIdleObjects();
747                for (final PooledObject<T> p : idleObjects) {
748                    // each item into the map using the PooledObject object as the
749                    // key. It then gets sorted based on the idle time
750                    map.put(p, k);
751                }
752            }
753        }
754
755        // Now iterate created map and kill the first 15% plus one to account
756        // for zero
757        int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
758        final Iterator<Map.Entry<PooledObject<T>, K>> iter =
759                map.entrySet().iterator();
760
761        while (iter.hasNext() && itemsToRemove > 0) {
762            final Map.Entry<PooledObject<T>, K> entry = iter.next();
763            // kind of backwards on naming.  In the map, each key is the
764            // PooledObject because it has the ordering with the timestamp
765            // value.  Each value that the key references is the key of the
766            // list it belongs to.
767            final K key = entry.getValue();
768            final PooledObject<T> p = entry.getKey();
769            // Assume the destruction succeeds
770            boolean destroyed = true;
771            try {
772                destroyed = destroy(key, p, false);
773            } catch (final Exception e) {
774                swallowException(e);
775            }
776            if (destroyed) {
777                itemsToRemove--;
778            }
779        }
780    }
781
782    /**
783     * Attempt to create one new instance to serve from the most heavily
784     * loaded pool that can add a new instance.
785     *
786     * This method exists to ensure liveness in the pool when threads are
787     * parked waiting and capacity to create instances under the requested keys
788     * subsequently becomes available.
789     *
790     * This method is not guaranteed to create an instance and its selection
791     * of the most loaded pool that can create an instance may not always be
792     * correct, since it does not lock the pool and instances may be created,
793     * borrowed, returned or destroyed by other threads while it is executing.
794     */
795    private void reuseCapacity() {
796        final int maxTotalPerKeySave = getMaxTotalPerKey();
797
798        // Find the most loaded pool that could take a new instance
799        int maxQueueLength = 0;
800        LinkedBlockingDeque<PooledObject<T>> mostLoaded = null;
801        K loadedKey = null;
802        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
803            final K k = entry.getKey();
804            final ObjectDeque<T> deque = entry.getValue();
805            if (deque != null) {
806                final LinkedBlockingDeque<PooledObject<T>> pool = deque.getIdleObjects();
807                final int queueLength = pool.getTakeQueueLength();
808                if (getNumActive(k) < maxTotalPerKeySave && queueLength > maxQueueLength) {
809                    maxQueueLength = queueLength;
810                    mostLoaded = pool;
811                    loadedKey = k;
812                }
813            }
814        }
815
816        // Attempt to add an instance to the most loaded pool
817        if (mostLoaded != null) {
818            register(loadedKey);
819            try {
820                final PooledObject<T> p = create(loadedKey);
821                if (p != null) {
822                    addIdleObject(loadedKey, p);
823                }
824            } catch (final Exception e) {
825                swallowException(e);
826            } finally {
827                deregister(loadedKey);
828            }
829        }
830    }
831
832    /**
833     * Checks to see if there are any threads currently waiting to borrow
834     * objects but are blocked waiting for more objects to become available.
835     *
836     * @return {@code true} if there is at least one thread waiting otherwise
837     *         {@code false}
838     */
839    private boolean hasBorrowWaiters() {
840        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
841            final ObjectDeque<T> deque = entry.getValue();
842            if (deque != null) {
843                final LinkedBlockingDeque<PooledObject<T>> pool =
844                        deque.getIdleObjects();
845                if(pool.hasTakeWaiters()) {
846                    return true;
847                }
848            }
849        }
850        return false;
851    }
852
853
854    /**
855     * {@inheritDoc}
856     * <p>
857     * Successive activations of this method examine objects in keyed sub-pools
858     * in sequence, cycling through the keys and examining objects in
859     * oldest-to-youngest order within the keyed sub-pools.
860     */
861    @Override
862    public void evict() throws Exception {
863        assertOpen();
864
865        if (getNumIdle() == 0) {
866            return;
867        }
868
869        PooledObject<T> underTest = null;
870        final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
871
872        synchronized (evictionLock) {
873            final EvictionConfig evictionConfig = new EvictionConfig(
874                    getMinEvictableIdleTimeMillis(),
875                    getSoftMinEvictableIdleTimeMillis(),
876                    getMinIdlePerKey());
877
878            final boolean testWhileIdle = getTestWhileIdle();
879
880            for (int i = 0, m = getNumTests(); i < m; i++) {
881                if(evictionIterator == null || !evictionIterator.hasNext()) {
882                    if (evictionKeyIterator == null ||
883                            !evictionKeyIterator.hasNext()) {
884                        final List<K> keyCopy = new ArrayList<>();
885                        final Lock readLock = keyLock.readLock();
886                        readLock.lock();
887                        try {
888                            keyCopy.addAll(poolKeyList);
889                        } finally {
890                            readLock.unlock();
891                        }
892                        evictionKeyIterator = keyCopy.iterator();
893                    }
894                    while (evictionKeyIterator.hasNext()) {
895                        evictionKey = evictionKeyIterator.next();
896                        final ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
897                        if (objectDeque == null) {
898                            continue;
899                        }
900
901                        final Deque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
902                        evictionIterator = new EvictionIterator(idleObjects);
903                        if (evictionIterator.hasNext()) {
904                            break;
905                        }
906                        evictionIterator = null;
907                    }
908                }
909                if (evictionIterator == null) {
910                    // Pools exhausted
911                    return;
912                }
913                final Deque<PooledObject<T>> idleObjects;
914                try {
915                    underTest = evictionIterator.next();
916                    idleObjects = evictionIterator.getIdleObjects();
917                } catch (final NoSuchElementException nsee) {
918                    // Object was borrowed in another thread
919                    // Don't count this as an eviction test so reduce i;
920                    i--;
921                    evictionIterator = null;
922                    continue;
923                }
924
925                if (!underTest.startEvictionTest()) {
926                    // Object was borrowed in another thread
927                    // Don't count this as an eviction test so reduce i;
928                    i--;
929                    continue;
930                }
931
932                // User provided eviction policy could throw all sorts of
933                // crazy exceptions. Protect against such an exception
934                // killing the eviction thread.
935                boolean evict;
936                try {
937                    evict = evictionPolicy.evict(evictionConfig, underTest,
938                            poolMap.get(evictionKey).getIdleObjects().size());
939                } catch (final Throwable t) {
940                    // Slightly convoluted as SwallowedExceptionListener
941                    // uses Exception rather than Throwable
942                    PoolUtils.checkRethrow(t);
943                    swallowException(new Exception(t));
944                    // Don't evict on error conditions
945                    evict = false;
946                }
947
948                if (evict) {
949                    destroy(evictionKey, underTest, true);
950                    destroyedByEvictorCount.incrementAndGet();
951                } else {
952                    if (testWhileIdle) {
953                        boolean active = false;
954                        try {
955                            factory.activateObject(evictionKey, underTest);
956                            active = true;
957                        } catch (final Exception e) {
958                            destroy(evictionKey, underTest, true);
959                            destroyedByEvictorCount.incrementAndGet();
960                        }
961                        if (active) {
962                            if (!factory.validateObject(evictionKey, underTest)) {
963                                destroy(evictionKey, underTest, true);
964                                destroyedByEvictorCount.incrementAndGet();
965                            } else {
966                                try {
967                                    factory.passivateObject(evictionKey, underTest);
968                                } catch (final Exception e) {
969                                    destroy(evictionKey, underTest, true);
970                                    destroyedByEvictorCount.incrementAndGet();
971                                }
972                            }
973                        }
974                    }
975                    if (!underTest.endEvictionTest(idleObjects)) {
976                        // TODO - May need to add code here once additional
977                        // states are used
978                    }
979                }
980            }
981        }
982    }
983
984    /**
985     * Create a new pooled object.
986     *
987     * @param key Key associated with new pooled object
988     *
989     * @return The new, wrapped pooled object
990     *
991     * @throws Exception If the objection creation fails
992     */
993    private PooledObject<T> create(final K key) throws Exception {
994        int maxTotalPerKeySave = getMaxTotalPerKey(); // Per key
995        if (maxTotalPerKeySave < 0) {
996            maxTotalPerKeySave = Integer.MAX_VALUE;
997        }
998        final int maxTotal = getMaxTotal();   // All keys
999
1000        final ObjectDeque<T> objectDeque = poolMap.get(key);
1001
1002        // Check against the overall limit
1003        boolean loop = true;
1004
1005        while (loop) {
1006            final int newNumTotal = numTotal.incrementAndGet();
1007            if (maxTotal > -1 && newNumTotal > maxTotal) {
1008                numTotal.decrementAndGet();
1009                if (getNumIdle() == 0) {
1010                    return null;
1011                }
1012                clearOldest();
1013            } else {
1014                loop = false;
1015            }
1016        }
1017
1018        // Flag that indicates if create should:
1019        // - TRUE:  call the factory to create an object
1020        // - FALSE: return null
1021        // - null:  loop and re-test the condition that determines whether to
1022        //          call the factory
1023        Boolean create = null;
1024        while (create == null) {
1025            synchronized (objectDeque.makeObjectCountLock) {
1026                final long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
1027                // Check against the per key limit
1028                if (newCreateCount > maxTotalPerKeySave) {
1029                    // The key is currently at capacity or in the process of
1030                    // making enough new objects to take it to capacity.
1031                    objectDeque.getCreateCount().decrementAndGet();
1032                    if (objectDeque.makeObjectCount == 0) {
1033                        // There are no makeObject() calls in progress for this
1034                        // key so the key is at capacity. Do not attempt to
1035                        // create a new object. Return and wait for an object to
1036                        // be returned.
1037                        create = Boolean.FALSE;
1038                    } else {
1039                        // There are makeObject() calls in progress that might
1040                        // bring the pool to capacity. Those calls might also
1041                        // fail so wait until they complete and then re-test if
1042                        // the pool is at capacity or not.
1043                        objectDeque.makeObjectCountLock.wait();
1044                    }
1045                } else {
1046                    // The pool is not at capacity. Create a new object.
1047                    objectDeque.makeObjectCount++;
1048                    create = Boolean.TRUE;
1049                }
1050            }
1051        }
1052
1053        if (!create.booleanValue()) {
1054            numTotal.decrementAndGet();
1055            return null;
1056        }
1057
1058        PooledObject<T> p = null;
1059        try {
1060            p = factory.makeObject(key);
1061        } catch (final Exception e) {
1062            numTotal.decrementAndGet();
1063            objectDeque.getCreateCount().decrementAndGet();
1064            throw e;
1065        } finally {
1066            synchronized (objectDeque.makeObjectCountLock) {
1067                objectDeque.makeObjectCount--;
1068                objectDeque.makeObjectCountLock.notifyAll();
1069            }
1070        }
1071
1072        createdCount.incrementAndGet();
1073        objectDeque.getAllObjects().put(new IdentityWrapper<>(p.getObject()), p);
1074        return p;
1075    }
1076
1077    /**
1078     * Destroy the wrapped, pooled object.
1079     *
1080     * @param key The key associated with the object to destroy.
1081     * @param toDestroy The wrapped object to be destroyed
1082     * @param always Should the object be destroyed even if it is not currently
1083     *               in the set of idle objects for the given key
1084     * @return {@code true} if the object was destroyed, otherwise {@code false}
1085     * @throws Exception If the object destruction failed
1086     */
1087    private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always)
1088            throws Exception {
1089
1090        final ObjectDeque<T> objectDeque = register(key);
1091
1092        try {
1093            final boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy);
1094
1095            if (isIdle || always) {
1096                objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject()));
1097                toDestroy.invalidate();
1098
1099                try {
1100                    factory.destroyObject(key, toDestroy);
1101                } finally {
1102                    objectDeque.getCreateCount().decrementAndGet();
1103                    destroyedCount.incrementAndGet();
1104                    numTotal.decrementAndGet();
1105                }
1106                return true;
1107            }
1108            return false;
1109        } finally {
1110            deregister(key);
1111        }
1112    }
1113
1114
1115    /**
1116     * Register the use of a key by an object.
1117     * <p>
1118     * register() and deregister() must always be used as a pair.
1119     *
1120     * @param k The key to register
1121     *
1122     * @return The objects currently associated with the given key. If this
1123     *         method returns without throwing an exception then it will never
1124     *         return null.
1125     */
1126    private ObjectDeque<T> register(final K k) {
1127        Lock lock = keyLock.readLock();
1128        ObjectDeque<T> objectDeque = null;
1129        try {
1130            lock.lock();
1131            objectDeque = poolMap.get(k);
1132            if (objectDeque == null) {
1133                // Upgrade to write lock
1134                lock.unlock();
1135                lock = keyLock.writeLock();
1136                lock.lock();
1137                objectDeque = poolMap.get(k);
1138                if (objectDeque == null) {
1139                    objectDeque = new ObjectDeque<>(fairness);
1140                    objectDeque.getNumInterested().incrementAndGet();
1141                    // NOTE: Keys must always be added to both poolMap and
1142                    //       poolKeyList at the same time while protected by
1143                    //       keyLock.writeLock()
1144                    poolMap.put(k, objectDeque);
1145                    poolKeyList.add(k);
1146                } else {
1147                    objectDeque.getNumInterested().incrementAndGet();
1148                }
1149            } else {
1150                objectDeque.getNumInterested().incrementAndGet();
1151            }
1152        } finally {
1153            lock.unlock();
1154        }
1155        return objectDeque;
1156    }
1157
1158    /**
1159     * De-register the use of a key by an object.
1160     * <p>
1161     * register() and deregister() must always be used as a pair.
1162     *
1163     * @param k The key to de-register
1164     */
1165    private void deregister(final K k) {
1166        ObjectDeque<T> objectDeque;
1167
1168        objectDeque = poolMap.get(k);
1169        final long numInterested = objectDeque.getNumInterested().decrementAndGet();
1170        if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
1171            // Potential to remove key
1172            final Lock writeLock = keyLock.writeLock();
1173            writeLock.lock();
1174            try {
1175                if (objectDeque.getCreateCount().get() == 0 &&
1176                        objectDeque.getNumInterested().get() == 0) {
1177                    // NOTE: Keys must always be removed from both poolMap and
1178                    //       poolKeyList at the same time while protected by
1179                    //       keyLock.writeLock()
1180                    poolMap.remove(k);
1181                    poolKeyList.remove(k);
1182                }
1183            } finally {
1184                writeLock.unlock();
1185            }
1186        }
1187    }
1188
1189    @Override
1190    void ensureMinIdle() throws Exception {
1191        final int minIdlePerKeySave = getMinIdlePerKey();
1192        if (minIdlePerKeySave < 1) {
1193            return;
1194        }
1195
1196        for (final K k : poolMap.keySet()) {
1197            ensureMinIdle(k);
1198        }
1199    }
1200
1201    /**
1202     * Ensure that the configured number of minimum idle objects is available in
1203     * the pool for the given key.
1204     *
1205     * @param key The key to check for idle objects
1206     *
1207     * @throws Exception If a new object is required and cannot be created
1208     */
1209    private void ensureMinIdle(final K key) throws Exception {
1210        // Calculate current pool objects
1211        ObjectDeque<T> objectDeque = poolMap.get(key);
1212
1213        // objectDeque == null is OK here. It is handled correctly by both
1214        // methods called below.
1215
1216        // this method isn't synchronized so the
1217        // calculateDeficit is done at the beginning
1218        // as a loop limit and a second time inside the loop
1219        // to stop when another thread already returned the
1220        // needed objects
1221        final int deficit = calculateDeficit(objectDeque);
1222
1223        for (int i = 0; i < deficit && calculateDeficit(objectDeque) > 0; i++) {
1224            addObject(key);
1225            // If objectDeque was null, it won't be any more. Obtain a reference
1226            // to it so the deficit can be correctly calculated. It needs to
1227            // take account of objects created in other threads.
1228            if (objectDeque == null) {
1229                objectDeque = poolMap.get(key);
1230            }
1231        }
1232    }
1233
1234    /**
1235     * Create an object using the {@link KeyedPooledObjectFactory#makeObject
1236     * factory}, passivate it, and then place it in the idle object pool.
1237     * <code>addObject</code> is useful for "pre-loading" a pool with idle
1238     * objects.
1239     *
1240     * @param key the key a new instance should be added to
1241     *
1242     * @throws Exception when {@link KeyedPooledObjectFactory#makeObject}
1243     *                   fails.
1244     */
1245    @Override
1246    public void addObject(final K key) throws Exception {
1247        assertOpen();
1248        register(key);
1249        try {
1250            final PooledObject<T> p = create(key);
1251            addIdleObject(key, p);
1252        } finally {
1253            deregister(key);
1254        }
1255    }
1256
1257    /**
1258     * Add an object to the set of idle objects for a given key.
1259     *
1260     * @param key The key to associate with the idle object
1261     * @param p The wrapped object to add.
1262     *
1263     * @throws Exception If the associated factory fails to passivate the object
1264     */
1265    private void addIdleObject(final K key, final PooledObject<T> p) throws Exception {
1266
1267        if (p != null) {
1268            factory.passivateObject(key, p);
1269            final LinkedBlockingDeque<PooledObject<T>> idleObjects =
1270                    poolMap.get(key).getIdleObjects();
1271            if (getLifo()) {
1272                idleObjects.addFirst(p);
1273            } else {
1274                idleObjects.addLast(p);
1275            }
1276        }
1277    }
1278
1279    /**
1280     * Registers a key for pool control and ensures that
1281     * {@link #getMinIdlePerKey()} idle instances are created.
1282     *
1283     * @param key - The key to register for pool control.
1284     *
1285     * @throws Exception If the associated factory throws an exception
1286     */
1287    public void preparePool(final K key) throws Exception {
1288        final int minIdlePerKeySave = getMinIdlePerKey();
1289        if (minIdlePerKeySave < 1) {
1290            return;
1291        }
1292        ensureMinIdle(key);
1293    }
1294
1295    /**
1296     * Calculate the number of objects to test in a run of the idle object
1297     * evictor.
1298     *
1299     * @return The number of objects to test for validity
1300     */
1301    private int getNumTests() {
1302        final int totalIdle = getNumIdle();
1303        final int numTests = getNumTestsPerEvictionRun();
1304        if (numTests >= 0) {
1305            return Math.min(numTests, totalIdle);
1306        }
1307        return(int)(Math.ceil(totalIdle/Math.abs((double)numTests)));
1308    }
1309
1310    /**
1311     * Calculate the number of objects that need to be created to attempt to
1312     * maintain the minimum number of idle objects while not exceeded the limits
1313     * on the maximum number of objects either per key or totally.
1314     *
1315     * @param objectDeque   The set of objects to check
1316     *
1317     * @return The number of new objects to create
1318     */
1319    private int calculateDeficit(final ObjectDeque<T> objectDeque) {
1320
1321        if (objectDeque == null) {
1322            return getMinIdlePerKey();
1323        }
1324
1325        // Used more than once so keep a local copy so the value is consistent
1326        final int maxTotal = getMaxTotal();
1327        final int maxTotalPerKeySave = getMaxTotalPerKey();
1328
1329        int objectDefecit = 0;
1330
1331        // Calculate no of objects needed to be created, in order to have
1332        // the number of pooled objects < maxTotalPerKey();
1333        objectDefecit = getMinIdlePerKey() - objectDeque.getIdleObjects().size();
1334        if (maxTotalPerKeySave > 0) {
1335            final int growLimit = Math.max(0,
1336                    maxTotalPerKeySave - objectDeque.getIdleObjects().size());
1337            objectDefecit = Math.min(objectDefecit, growLimit);
1338        }
1339
1340        // Take the maxTotal limit into account
1341        if (maxTotal > 0) {
1342            final int growLimit = Math.max(0, maxTotal - getNumActive() - getNumIdle());
1343            objectDefecit = Math.min(objectDefecit, growLimit);
1344        }
1345
1346        return objectDefecit;
1347    }
1348
1349
1350    //--- JMX support ----------------------------------------------------------
1351
1352    @Override
1353    public Map<String,Integer> getNumActivePerKey() {
1354        final HashMap<String,Integer> result = new HashMap<>();
1355
1356        final Iterator<Entry<K,ObjectDeque<T>>> iter = poolMap.entrySet().iterator();
1357        while (iter.hasNext()) {
1358            final Entry<K,ObjectDeque<T>> entry = iter.next();
1359            if (entry != null) {
1360                final K key = entry.getKey();
1361                final ObjectDeque<T> objectDequeue = entry.getValue();
1362                if (key != null && objectDequeue != null) {
1363                    result.put(key.toString(), Integer.valueOf(
1364                            objectDequeue.getAllObjects().size() -
1365                            objectDequeue.getIdleObjects().size()));
1366                }
1367            }
1368        }
1369        return result;
1370    }
1371
1372    /**
1373     * Return an estimate of the number of threads currently blocked waiting for
1374     * an object from the pool. This is intended for monitoring only, not for
1375     * synchronization control.
1376     *
1377     * @return The estimate of the number of threads currently blocked waiting
1378     *         for an object from the pool
1379     */
1380    @Override
1381    public int getNumWaiters() {
1382        int result = 0;
1383
1384        if (getBlockWhenExhausted()) {
1385            final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
1386
1387            while (iter.hasNext()) {
1388                // Assume no overflow
1389                result += iter.next().getIdleObjects().getTakeQueueLength();
1390            }
1391        }
1392
1393        return result;
1394    }
1395
1396    /**
1397     * Return an estimate of the number of threads currently blocked waiting for
1398     * an object from the pool for each key. This is intended for
1399     * monitoring only, not for synchronization control.
1400     *
1401     * @return The estimate of the number of threads currently blocked waiting
1402     *         for an object from the pool for each key
1403     */
1404    @Override
1405    public Map<String,Integer> getNumWaitersByKey() {
1406        final Map<String,Integer> result = new HashMap<>();
1407
1408        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
1409            final K k = entry.getKey();
1410            final ObjectDeque<T> deque = entry.getValue();
1411            if (deque != null) {
1412                if (getBlockWhenExhausted()) {
1413                    result.put(k.toString(), Integer.valueOf(
1414                            deque.getIdleObjects().getTakeQueueLength()));
1415                } else {
1416                    result.put(k.toString(), Integer.valueOf(0));
1417                }
1418            }
1419        }
1420        return result;
1421    }
1422
1423    /**
1424     * Provides information on all the objects in the pool, both idle (waiting
1425     * to be borrowed) and active (currently borrowed).
1426     * <p>
1427     * Note: This is named listAllObjects so it is presented as an operation via
1428     * JMX. That means it won't be invoked unless the explicitly requested
1429     * whereas all attributes will be automatically requested when viewing the
1430     * attributes for an object in a tool like JConsole.
1431     *
1432     * @return Information grouped by key on all the objects in the pool
1433     */
1434    @Override
1435    public Map<String,List<DefaultPooledObjectInfo>> listAllObjects() {
1436        final Map<String,List<DefaultPooledObjectInfo>> result =
1437                new HashMap<>();
1438
1439        for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
1440            final K k = entry.getKey();
1441            final ObjectDeque<T> deque = entry.getValue();
1442            if (deque != null) {
1443                final List<DefaultPooledObjectInfo> list =
1444                        new ArrayList<>();
1445                result.put(k.toString(), list);
1446                for (final PooledObject<T> p : deque.getAllObjects().values()) {
1447                    list.add(new DefaultPooledObjectInfo(p));
1448                }
1449            }
1450        }
1451        return result;
1452    }
1453
1454
1455    //--- inner classes ----------------------------------------------
1456
1457    /**
1458     * Maintains information on the per key queue for a given key.
1459     *
1460     * @param <S> type of objects in the pool
1461     */
1462    private class ObjectDeque<S> {
1463
1464        private final LinkedBlockingDeque<PooledObject<S>> idleObjects;
1465
1466        /*
1467         * Number of instances created - number destroyed.
1468         * Invariant: createCount <= maxTotalPerKey
1469         */
1470        private final AtomicInteger createCount = new AtomicInteger(0);
1471
1472        private long makeObjectCount = 0;
1473        private final Object makeObjectCountLock = new Object();
1474
1475        /*
1476         * The map is keyed on pooled instances, wrapped to ensure that
1477         * they work properly as keys.
1478         */
1479        private final Map<IdentityWrapper<S>, PooledObject<S>> allObjects =
1480                new ConcurrentHashMap<>();
1481
1482        /*
1483         * Number of threads with registered interest in this key.
1484         * register(K) increments this counter and deRegister(K) decrements it.
1485         * Invariant: empty keyed pool will not be dropped unless numInterested
1486         *            is 0.
1487         */
1488        private final AtomicLong numInterested = new AtomicLong(0);
1489
1490        /**
1491         * Create a new ObjecDeque with the given fairness policy.
1492         * @param fairness true means client threads waiting to borrow / return instances
1493         * will be served as if waiting in a FIFO queue.
1494         */
1495        public ObjectDeque(final boolean fairness) {
1496            idleObjects = new LinkedBlockingDeque<>(fairness);
1497        }
1498
1499        /**
1500         * Obtain the idle objects for the current key.
1501         *
1502         * @return The idle objects
1503         */
1504        public LinkedBlockingDeque<PooledObject<S>> getIdleObjects() {
1505            return idleObjects;
1506        }
1507
1508        /**
1509         * Obtain the count of the number of objects created for the current
1510         * key.
1511         *
1512         * @return The number of objects created for this key
1513         */
1514        public AtomicInteger getCreateCount() {
1515            return createCount;
1516        }
1517
1518        /**
1519         * Obtain the number of threads with an interest registered in this key.
1520         *
1521         * @return The number of threads with a registered interest in this key
1522         */
1523        public AtomicLong getNumInterested() {
1524            return numInterested;
1525        }
1526
1527        /**
1528         * Obtain all the objects for the current key.
1529         *
1530         * @return All the objects
1531         */
1532        public Map<IdentityWrapper<S>, PooledObject<S>> getAllObjects() {
1533            return allObjects;
1534        }
1535
1536        @Override
1537        public String toString() {
1538            final StringBuilder builder = new StringBuilder();
1539            builder.append("ObjectDeque [idleObjects=");
1540            builder.append(idleObjects);
1541            builder.append(", createCount=");
1542            builder.append(createCount);
1543            builder.append(", allObjects=");
1544            builder.append(allObjects);
1545            builder.append(", numInterested=");
1546            builder.append(numInterested);
1547            builder.append("]");
1548            return builder.toString();
1549        }
1550
1551    }
1552
1553    //--- configuration attributes ---------------------------------------------
1554    private volatile int maxIdlePerKey =
1555            GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY;
1556    private volatile int minIdlePerKey =
1557            GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY;
1558    private volatile int maxTotalPerKey =
1559            GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;
1560    private final KeyedPooledObjectFactory<K,T> factory;
1561    private final boolean fairness;
1562
1563
1564    //--- internal attributes --------------------------------------------------
1565
1566    /*
1567     * My hash of sub-pools (ObjectQueue). The list of keys <b>must</b> be kept
1568     * in step with {@link #poolKeyList} using {@link #keyLock} to ensure any
1569     * changes to the list of current keys is made in a thread-safe manner.
1570     */
1571    private final Map<K,ObjectDeque<T>> poolMap =
1572            new ConcurrentHashMap<>(); // @GuardedBy("keyLock") for write access (and some read access)
1573    /*
1574     * List of pool keys - used to control eviction order. The list of keys
1575     * <b>must</b> be kept in step with {@link #poolMap} using {@link #keyLock}
1576     * to ensure any changes to the list of current keys is made in a
1577     * thread-safe manner.
1578     */
1579    private final List<K> poolKeyList = new ArrayList<>(); // @GuardedBy("keyLock")
1580    private final ReadWriteLock keyLock = new ReentrantReadWriteLock(true);
1581    /*
1582     * The combined count of the currently active objects for all keys and those
1583     * in the process of being created. Under load, it may exceed
1584     * {@link #maxTotal} but there will never be more than {@link #maxTotal}
1585     * created at any one time.
1586     */
1587    private final AtomicInteger numTotal = new AtomicInteger(0);
1588    private Iterator<K> evictionKeyIterator = null; // @GuardedBy("evictionLock")
1589    private K evictionKey = null; // @GuardedBy("evictionLock")
1590
1591    // JMX specific attributes
1592    private static final String ONAME_BASE =
1593            "org.apache.commons.pool2:type=GenericKeyedObjectPool,name=";
1594
1595    @Override
1596    protected void toStringAppendFields(final StringBuilder builder) {
1597        super.toStringAppendFields(builder);
1598        builder.append(", maxIdlePerKey=");
1599        builder.append(maxIdlePerKey);
1600        builder.append(", minIdlePerKey=");
1601        builder.append(minIdlePerKey);
1602        builder.append(", maxTotalPerKey=");
1603        builder.append(maxTotalPerKey);
1604        builder.append(", factory=");
1605        builder.append(factory);
1606        builder.append(", fairness=");
1607        builder.append(fairness);
1608        builder.append(", poolMap=");
1609        builder.append(poolMap);
1610        builder.append(", poolKeyList=");
1611        builder.append(poolKeyList);
1612        builder.append(", keyLock=");
1613        builder.append(keyLock);
1614        builder.append(", numTotal=");
1615        builder.append(numTotal);
1616        builder.append(", evictionKeyIterator=");
1617        builder.append(evictionKeyIterator);
1618        builder.append(", evictionKey=");
1619        builder.append(evictionKey);
1620    }
1621}