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