Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Licensed to the Apache Software Foundation (ASF) under one or more
    * contributor license agreements.  See the NOTICE file distributed with
    * this work for additional information regarding copyright ownership.
    * The ASF licenses this file to You under the Apache License, Version 2.0
    * (the "License"); you may not use this file except in compliance with
    * the License.  You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.commons.pool.impl;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.TreeMap;
  
A configurable KeyedObjectPool implementation.

When coupled with the appropriate org.apache.commons.pool.KeyedPoolableObjectFactory, GenericKeyedObjectPool provides robust pooling functionality for keyed objects. A GenericKeyedObjectPool can be viewed as a map of pools, keyed on the (unique) key values provided to the preparePool, addObject or borrowObject methods. Each time a new key value is provided to one of these methods, a new pool is created under the given key to be managed by the containing GenericKeyedObjectPool.

A GenericKeyedObjectPool provides a number of configurable parameters:

  • maxActive controls the maximum number of objects (per key) that can allocated by the pool (checked out to client threads, or idle in the pool) at one time. When non-positive, there is no limit to the number of objects per key. When maxActive is reached, the keyed pool is said to be exhausted. The default setting for this parameter is 8.
  • maxTotal sets a global limit on the number of objects that can be in circulation (active or idle) within the combined set of pools. When non-positive, there is no limit to the total number of objects in circulation. When maxTotal is exceeded, all keyed pools are exhausted. When maxTotal is set to a positive value and borrowObject is invoked when at the limit with no idle instances available, an attempt is made to create room by clearing the oldest 15% of the elements from the keyed pools. The default setting for this parameter is -1 (no limit).
  • maxIdle controls the maximum number of objects that can sit idle in the pool (per key) at any time. When negative, there is no limit to the number of objects that may be idle per key. The default setting for this parameter is 8.
  • whenExhaustedAction specifies the behavior of the borrowObject method when a keyed pool is exhausted:
    • When whenExhaustedAction is WHEN_EXHAUSTED_FAIL, borrowObject will throw a java.util.NoSuchElementException
    • When whenExhaustedAction is WHEN_EXHAUSTED_GROW, borrowObject will create a new object and return it (essentially making maxActive meaningless.)
    • When whenExhaustedAction is WHEN_EXHAUSTED_BLOCK, borrowObject will block (invoke wait until a new or idle object is available. If a positive maxWait value is supplied, the borrowObject will block for at most that many milliseconds, after which a java.util.NoSuchElementException will be thrown. If maxWait is non-positive, the borrowObject method will block indefinitely.
    The default whenExhaustedAction setting is WHEN_EXHAUSTED_BLOCK.
  • When testOnBorrow is set, the pool will attempt to validate each object before it is returned from the borrowObject method. (Using the provided factory's validateObject method.) Objects that fail to validate will be dropped from the pool, and a different object will be borrowed. The default setting for this parameter is false.
  • When testOnReturn is set, the pool will attempt to validate each object before it is returned to the pool in the returnObject method. (Using the provided factory's validateObject method.) Objects that fail to validate will be dropped from the pool. The default setting for this parameter is false.

Optionally, one may configure the pool to examine and possibly evict objects as they sit idle in the pool and to ensure that a minimum number of idle objects is maintained for each key. This is performed by an "idle object eviction" thread, which runs asynchronously. Caution should be used when configuring this optional feature. Eviction runs contend with client threads for access to objects in the pool, so if they run too frequently performance issues may result. The idle object eviction thread may be configured using the following attributes:

  • timeBetweenEvictionRunsMillis indicates how long the eviction thread should sleep before "runs" of examining idle objects. When non-positive, no eviction thread will be launched. The default setting for this parameter is -1 (i.e., by default, idle object eviction is disabled).
  • minEvictableIdleTimeMillis specifies the minimum amount of time that an object may sit idle in the pool before it is eligible for eviction due to idle time. When non-positive, no object will be dropped from the pool due to idle time alone. This setting has no effect unless timeBetweenEvictionRunsMillis > 0. The default setting for this parameter is 30 minutes.
  • testWhileIdle indicates whether or not idle objects should be validated using the factory's validateObject method during idle object eviction runs. Objects that fail to validate will be dropped from the pool. This setting has no effect unless timeBetweenEvictionRunsMillis > 0. The default setting for this parameter is false.
  • minIdle sets a target value for the minimum number of idle objects (per key) that should always be available. If this parameter is set to a positive number and timeBetweenEvictionRunsMillis > 0, each time the idle object eviction thread runs, it will try to create enough idle instances so that there will be minIdle idle instances available under each key. This parameter is also used by preparePool if true is provided as that method's populateImmediately parameter. The default setting for this parameter is 0.

The pools can be configured to behave as LIFO queues with respect to idle objects - always returning the most recently used object from the pool, or as FIFO queues, where borrowObject always returns the oldest object in the idle object pool.

  • Lifo determines whether or not the pools return idle objects in last-in-first-out order. The default setting for this parameter is true.

GenericKeyedObjectPool is not usable without a org.apache.commons.pool.KeyedPoolableObjectFactory. A non-null factory must be provided either as a constructor argument or via a call to setFactory before the pool is used.

Implementation note: To prevent possible deadlocks, care has been taken to ensure that no call to a factory method will occur within a synchronization block. See POOL-125 and DBCP-44 for more information.

Parameters:
<K> the type of keys in this pool
<V> the type of objects held in this pool
Author(s):
Rodney Waldhoff
Dirk Verbeeck
Sandy McArthur
Version:
$Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $
Since:
Pool 1.0
See also:
GenericObjectPool
 
 public class GenericKeyedObjectPool<K, V> extends BaseKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
 
     //--- public constants -------------------------------------------
 
    
A "when exhausted action" type indicating that when the pool is exhausted (i.e., the maximum number of active objects has been reached), the borrowObject(java.lang.Object) method should fail, throwing a java.util.NoSuchElementException.

 
     public static final byte WHEN_EXHAUSTED_FAIL   = 0;

    
A "when exhausted action" type indicating that when the pool is exhausted (i.e., the maximum number of active objects has been reached), the borrowObject(java.lang.Object) method should block until a new object is available, or the maximum wait time has been reached.

 
     public static final byte WHEN_EXHAUSTED_BLOCK  = 1;

    
A "when exhausted action" type indicating that when the pool is exhausted (i.e., the maximum number of active objects has been reached), the borrowObject(java.lang.Object) method should simply create a new object anyway.

 
     public static final byte WHEN_EXHAUSTED_GROW   = 2;

    
The default cap on the number of idle instances (per key) in the pool.

 
     public static final int DEFAULT_MAX_IDLE  = 8;

    
The default cap on the total number of active instances (per key) from the pool.

 
     public static final int DEFAULT_MAX_ACTIVE  = 8;

    
The default cap on the the overall maximum number of objects that can exist at one time.

 
     public static final int DEFAULT_MAX_TOTAL  = -1;

    
The default "when exhausted action" for the pool.

 
     public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = ;

    
The default maximum amount of time (in milliseconds) the borrowObject(java.lang.Object) method should block before throwing an exception when the pool is exhausted and the "when exhausted" action is WHEN_EXHAUSTED_BLOCK.

 
     public static final long DEFAULT_MAX_WAIT = -1L;

    
The default "test on borrow" value.

 
     public static final boolean DEFAULT_TEST_ON_BORROW = false;

    
The default "test on return" value.

 
     public static final boolean DEFAULT_TEST_ON_RETURN = false;

    
 
     public static final boolean DEFAULT_TEST_WHILE_IDLE = false;

    
The default "time between eviction runs" value.

 
     public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;

    
The default number of objects to examine per run in the idle object evictor.

 
     public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;

    
 
     public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;

    
The default minimum level of idle objects in the pool.

Since:
Pool 1.3
See also:
setMinIdle(int)
getMinIdle()
 
     public static final int DEFAULT_MIN_IDLE = 0;

    
The default LIFO status. True means that borrowObject returns the most recently used ("last in") idle object in a pool (if there are idle instances available). False means that pools behave as FIFO queues - objects are taken from idle object pools in the order that they are returned.

 
     public static final boolean DEFAULT_LIFO = true;
 
     //--- constructors -----------------------------------------------
 
    
 
     public GenericKeyedObjectPool() {
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factory) {
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
config a non-null GenericKeyedObjectPool.Config describing the configuration
 
         this(factoryconfig.maxActiveconfig.whenExhaustedActionconfig.maxWaitconfig.maxIdleconfig.maxTotal,
                 config.minIdleconfig.testOnBorrowconfig.testOnReturnconfig.timeBetweenEvictionRunsMillis,
                 config.numTestsPerEvictionRunconfig.minEvictableIdleTimeMillisconfig.testWhileIdleconfig.lifo);
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActive) {
         this(factory,maxActive,
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWait) {
         this(factorymaxActivewhenExhaustedActionmaxWait,
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitboolean testOnBorrowboolean testOnReturn) {
         this(factorymaxActivewhenExhaustedActionmaxWait,testOnBorrow,testOnReturn,
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdle) {
         this(factorymaxActivewhenExhaustedActionmaxWaitmaxIdle,
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see getMaxWait())
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdleboolean testOnBorrowboolean testOnReturn) {
         this(factorymaxActivewhenExhaustedActionmaxWaitmaxIdletestOnBorrowtestOnReturn,
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see setTimeBetweenEvictionRunsMillis(long))
numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see setNumTestsPerEvictionRun(int))
minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see setMinEvictableIdleTimeMillis(long))
testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see setTestWhileIdle(boolean))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdleboolean testOnBorrowboolean testOnReturnlong timeBetweenEvictionRunsMillis,
             int numTestsPerEvictionRunlong minEvictableIdleTimeMillisboolean testWhileIdle) {
         this(factorymaxActivewhenExhaustedActionmaxWaitmaxIdle.,
                 testOnBorrowtestOnReturntimeBetweenEvictionRunsMillisnumTestsPerEvictionRun,
                 minEvictableIdleTimeMillistestWhileIdle);
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed from me at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
maxTotal the maximum number of objects that can exists at one time (see setMaxTotal(int))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see setTimeBetweenEvictionRunsMillis(long))
numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see setNumTestsPerEvictionRun(int))
minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see setMinEvictableIdleTimeMillis(long))
testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see setTestWhileIdle(boolean))
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdleint maxTotalboolean testOnBorrowboolean testOnReturn,
             long timeBetweenEvictionRunsMillisint numTestsPerEvictionRunlong minEvictableIdleTimeMillis,
             boolean testWhileIdle) {
         this(factorymaxActivewhenExhaustedActionmaxWaitmaxIdlemaxTotal,
                 .testOnBorrowtestOnReturntimeBetweenEvictionRunsMillis,
                 numTestsPerEvictionRunminEvictableIdleTimeMillistestWhileIdle);
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
maxTotal the maximum number of objects that can exists at one time (see setMaxTotal(int))
minIdle the minimum number of idle objects to have in the pool at any one time (see setMinIdle(int))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see setTimeBetweenEvictionRunsMillis(long))
numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see setNumTestsPerEvictionRun(int))
minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see setMinEvictableIdleTimeMillis(long))
testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see setTestWhileIdle(boolean))
Since:
Pool 1.3
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdleint maxTotalint minIdleboolean testOnBorrowboolean testOnReturn,
             long timeBetweenEvictionRunsMillisint numTestsPerEvictionRunlong minEvictableIdleTimeMillis,
             boolean testWhileIdle) {
         this(factorymaxActivewhenExhaustedActionmaxWaitmaxIdlemaxTotalminIdletestOnBorrowtestOnReturn,
                 timeBetweenEvictionRunsMillisnumTestsPerEvictionRunminEvictableIdleTimeMillistestWhileIdle,
                 );
     }

    
Create a new GenericKeyedObjectPool using the specified values.

Parameters:
factory the KeyedPoolableObjectFactory to use to create, validate, and destroy objects if not null
maxActive the maximum number of objects that can be borrowed at one time (see setMaxActive(int))
whenExhaustedAction the action to take when the pool is exhausted (see setWhenExhaustedAction(byte))
maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction is WHEN_EXHAUSTED_BLOCK (otherwise ignored) (see setMaxWait(long))
maxIdle the maximum number of idle objects in my pool (see setMaxIdle(int))
maxTotal the maximum number of objects that can exists at one time (see setMaxTotal(int))
minIdle the minimum number of idle objects to have in the pool at any one time (see setMinIdle(int))
testOnBorrow whether or not to validate objects before they are returned by the borrowObject(java.lang.Object) method (see setTestOnBorrow(boolean))
testOnReturn whether or not to validate objects after they are returned to the returnObject(java.lang.Object,java.lang.Object) method (see setTestOnReturn(boolean))
timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see setTimeBetweenEvictionRunsMillis(long))
numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see setNumTestsPerEvictionRun(int))
minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see setMinEvictableIdleTimeMillis(long))
testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see setTestWhileIdle(boolean))
lifo whether or not the pools behave as LIFO (last in first out) queues (see setLifo(boolean))
Since:
Pool 1.4
 
     public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K, V> factoryint maxActivebyte whenExhaustedAction,
             long maxWaitint maxIdleint maxTotalint minIdleboolean testOnBorrowboolean testOnReturn,
             long timeBetweenEvictionRunsMillisint numTestsPerEvictionRunlong minEvictableIdleTimeMillis,
             boolean testWhileIdleboolean lifo) {
          = factory;
          = maxActive;
          = lifo;
         switch (whenExhaustedAction) {
             case :
             case :
             case :
                  = whenExhaustedAction;
                 break;
             default:
                 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
         }
          = maxWait;
          = maxIdle;
          = maxTotal;
          = minIdle;
          = testOnBorrow;
          = testOnReturn;
          = timeBetweenEvictionRunsMillis;
          = numTestsPerEvictionRun;
          = minEvictableIdleTimeMillis;
          = testWhileIdle;
 
          = new HashMap<K, ObjectQueue>();
          = new CursorableLinkedList<K>();
 
     }
 
     //--- public methods ---------------------------------------------
 
     //--- configuration methods --------------------------------------
 
    
Returns the cap on the number of object instances allocated by the pool (checked out or idle), per key. A negative value indicates no limit.

Returns:
the cap on the number of active instances per key.
See also:
setMaxActive(int)
 
     public synchronized int getMaxActive() {
         return ;
     }

    
Sets the cap on the number of object instances managed by the pool per key.

Parameters:
maxActive The cap on the number of object instances per key. Use a negative value for no limit.
See also:
getMaxActive()
 
     public void setMaxActive(int maxActive) {
         synchronized(this) {
              = maxActive;
         }
         allocate();
     }

    
Returns the overall maximum number of objects (across pools) that can exist at one time. A negative value indicates no limit.

Returns:
the maximum number of instances in circulation at one time.
See also:
setMaxTotal(int)
 
     public synchronized int getMaxTotal() {
         return ;
     }

    
Sets the cap on the total number of instances from all pools combined. When maxTotal is set to a positive value and borrowObject is invoked when at the limit with no idle instances available, an attempt is made to create room by clearing the oldest 15% of the elements from the keyed pools.

Parameters:
maxTotal The cap on the total number of instances across pools. Use a negative value for no limit.
See also:
getMaxTotal()
 
     public void setMaxTotal(int maxTotal) {
         synchronized(this) {
              = maxTotal;
         }
         allocate();
     }

    
Returns the action to take when the borrowObject(java.lang.Object) method is invoked when the pool is exhausted (the maximum number of "active" objects has been reached).

 
     public synchronized byte getWhenExhaustedAction() {
         return ;
     }

    
Sets the action to take when the borrowObject(java.lang.Object) method is invoked when the pool is exhausted (the maximum number of "active" objects has been reached).

Parameters:
whenExhaustedAction the action code, which must be one of WHEN_EXHAUSTED_BLOCK, WHEN_EXHAUSTED_FAIL, or WHEN_EXHAUSTED_GROW
See also:
getWhenExhaustedAction()
 
     public void setWhenExhaustedAction(byte whenExhaustedAction) {
         synchronized(this) {
             switch(whenExhaustedAction) {
                 case :
                 case :
                 case :
                      = whenExhaustedAction;
                     break;
                 default:
                     throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
             }
         }
         allocate();
     }


    
Returns the maximum amount of time (in milliseconds) the borrowObject(java.lang.Object) method should block before throwing an exception when the pool is exhausted and the "when exhausted" action is WHEN_EXHAUSTED_BLOCK. When less than or equal to 0, the borrowObject(java.lang.Object) method may block indefinitely.

Returns:
the maximum number of milliseconds borrowObject will block.
See also:
setMaxWait(long)
setWhenExhaustedAction(byte)
WHEN_EXHAUSTED_BLOCK
 
     public synchronized long getMaxWait() {
         return ;
     }

    
Sets the maximum amount of time (in milliseconds) the borrowObject(java.lang.Object) method should block before throwing an exception when the pool is exhausted and the "when exhausted" action is WHEN_EXHAUSTED_BLOCK. When less than or equal to 0, the borrowObject(java.lang.Object) method may block indefinitely.

Parameters:
maxWait the maximum number of milliseconds borrowObject will block or negative for indefinitely.
See also:
getMaxWait()
setWhenExhaustedAction(byte)
WHEN_EXHAUSTED_BLOCK
 
     public void setMaxWait(long maxWait) {
         synchronized(this) {
              = maxWait;
         }
         allocate();
     }

    
Returns the cap on the number of "idle" instances per key.

Returns:
the maximum number of "idle" instances that can be held in a given keyed pool.
See also:
setMaxIdle(int)
 
     public synchronized int getMaxIdle() {
         return ;
     }

    
Sets the cap on the number of "idle" instances in the pool. If maxIdle is set too low on heavily loaded systems it is possible you will see objects being destroyed and almost immediately new objects being created. This is a result of the active threads momentarily returning objects faster than they are requesting them them, causing the number of idle objects to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good starting point.

Parameters:
maxIdle the maximum number of "idle" instances that can be held in a given keyed pool. Use a negative value for no limit.
See also:
getMaxIdle()
DEFAULT_MAX_IDLE
 
     public void setMaxIdle(int maxIdle) {
         synchronized(this) {
              = maxIdle;
         }
         allocate();
     }

    
Sets the minimum number of idle objects to maintain in each of the keyed pools. This setting has no effect unless timeBetweenEvictionRunsMillis > 0 and attempts to ensure that each pool has the required minimum number of instances are only made during idle object eviction runs.

Parameters:
poolSize - The minimum size of the each keyed pool
Since:
Pool 1.3
See also:
getMinIdle()
setTimeBetweenEvictionRunsMillis(long)
 
     public void setMinIdle(int poolSize) {
          = poolSize;
     }

    
Returns the minimum number of idle objects to maintain in each of the keyed pools. This setting has no effect unless timeBetweenEvictionRunsMillis > 0 and attempts to ensure that each pool has the required minimum number of instances are only made during idle object eviction runs.

Returns:
minimum size of the each keyed pool
Since:
Pool 1.3
See also:
setTimeBetweenEvictionRunsMillis(long)
 
     public int getMinIdle() {
         return ;
     }

    
When true, objects will be validated before being returned by the borrowObject(java.lang.Object) method. If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another.

Returns:
true if objects are validated before being borrowed.
See also:
setTestOnBorrow(boolean)
 
     public boolean getTestOnBorrow() {
         return ;
     }

    
When true, objects will be validated before being returned by the borrowObject(java.lang.Object) method. If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another.

Parameters:
testOnBorrow whether object should be validated before being returned by borrowObject.
See also:
getTestOnBorrow()
 
     public void setTestOnBorrow(boolean testOnBorrow) {
          = testOnBorrow;
     }

    
When true, objects will be validated before being returned to the pool within the returnObject(java.lang.Object,java.lang.Object).

Returns:
true when objects will be validated before being returned.
See also:
setTestOnReturn(boolean)
 
     public boolean getTestOnReturn() {
         return ;
     }

    
When true, objects will be validated before being returned to the pool within the returnObject(java.lang.Object,java.lang.Object).

Parameters:
testOnReturn true so objects will be validated before being returned.
See also:
getTestOnReturn()
 
     public void setTestOnReturn(boolean testOnReturn) {
          = testOnReturn;
     }

    
Returns the number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run.

Returns:
milliseconds to sleep between evictor runs.
See also:
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized long getTimeBetweenEvictionRunsMillis() {
         return ;
     }

    
Sets the number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run.

Parameters:
timeBetweenEvictionRunsMillis milliseconds to sleep between evictor runs.
See also:
getTimeBetweenEvictionRunsMillis()
 
     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
          = timeBetweenEvictionRunsMillis;
     }

    
Returns the max number of objects to examine during each run of the idle object evictor thread (if any).

Returns:
number of objects to examine each eviction run.
See also:
setNumTestsPerEvictionRun(int)
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized int getNumTestsPerEvictionRun() {
         return ;
     }

    
Sets the max number of objects to examine during each run of the idle object evictor thread (if any).

When a negative value is supplied, ceil(getNumIdle())/abs(getNumTestsPerEvictionRun()) tests will be run. I.e., when the value is -n, roughly one nth of the idle objects will be tested per run. When the value is positive, the number of tests actually performed in each run will be the minimum of this value and the number of instances idle in the pools.

Parameters:
numTestsPerEvictionRun number of objects to examine each eviction run.
See also:
setNumTestsPerEvictionRun(int)
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
          = numTestsPerEvictionRun;
     }

    
Returns the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any).

Returns:
minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
See also:
setMinEvictableIdleTimeMillis(long)
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized long getMinEvictableIdleTimeMillis() {
         return ;
     }

    
Sets the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle time alone.

Parameters:
minEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
See also:
getMinEvictableIdleTimeMillis()
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
          = minEvictableIdleTimeMillis;
     }

    
When true, objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool.

Returns:
true when objects are validated when borrowed.
See also:
setTestWhileIdle(boolean)
setTimeBetweenEvictionRunsMillis(long)
 
     public synchronized boolean getTestWhileIdle() {
         return ;
     }

    
When true, objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool.

Parameters:
testWhileIdle true so objects are validated when borrowed.
See also:
getTestWhileIdle()
setTimeBetweenEvictionRunsMillis(long)
    public synchronized void setTestWhileIdle(boolean testWhileIdle) {
         = testWhileIdle;
    }

    
Sets the configuration.

Parameters:
conf the new configuration to use.
See also:
GenericKeyedObjectPool.Config
    public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
        setMaxIdle(conf.maxIdle);
        setMaxActive(conf.maxActive);
        setMaxTotal(conf.maxTotal);
        setMinIdle(conf.minIdle);
        setMaxWait(conf.maxWait);
        setWhenExhaustedAction(conf.whenExhaustedAction);
        setTestOnBorrow(conf.testOnBorrow);
        setTestOnReturn(conf.testOnReturn);
        setTestWhileIdle(conf.testWhileIdle);
        setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
        setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
        setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
    }

    
Whether or not the idle object pools act as LIFO queues. True means that borrowObject returns the most recently used ("last in") idle object in a pool (if there are idle instances available). False means that the pools behave as FIFO queues - objects are taken from idle object pools in the order that they are returned.

Returns:
true if the pools are configured to act as LIFO queues
Since:
1.4
     public synchronized boolean getLifo() {
         return ;
     }

     
Sets the LIFO property of the pools. True means that borrowObject returns the most recently used ("last in") idle object in a pool (if there are idle instances available). False means that the pools behave as FIFO queues - objects are taken from idle object pools in the order that they are returned.

Parameters:
lifo the new value for the lifo property
Since:
1.4
     public synchronized void setLifo(boolean lifo) {
         this. = lifo;
     }
    //-- ObjectPool methods ------------------------------------------

    

Borrows an object from the keyed pool associated with the given key.

If there is an idle instance available in the pool associated with the given key, then either the most-recently returned (if lifo == true) or "oldest" (lifo == false) instance sitting idle in the pool will be activated and returned. If activation fails, or testOnBorrow is set to true and validation fails, the instance is destroyed and the next available instance is examined. This continues until either a valid instance is returned or there are no more idle instances available.

If there are no idle instances available in the pool associated with the given key, behavior depends on the maxActive, maxTotal, and (if applicable) whenExhaustedAction and maxWait properties. If the number of instances checked out from the pool under the given key is less than maxActive and the total number of instances in circulation (under all keys) is less than maxTotal, a new instance is created, activated and (if applicable) validated and returned to the caller.

If the associated keyed pool is exhausted (no available idle instances and no capacity to create new ones), this method will either block (WHEN_EXHAUSTED_BLOCK), throw a NoSuchElementException (WHEN_EXHAUSTED_FAIL), or grow (WHEN_EXHAUSTED_GROW - ignoring maxActive, maxTotal properties). The length of time that this method will block when whenExhaustedAction == WHEN_EXHAUSTED_BLOCK is determined by the maxWait property.

When the pool is exhausted, multiple calling threads may be simultaneously blocked waiting for instances to become available. As of pool 1.5, a "fairness" algorithm has been implemented to ensure that threads receive available instances in request arrival order.

Parameters:
key pool key
Returns:
object instance from the keyed pool
Throws:
java.util.NoSuchElementException if a keyed object instance cannot be returned.
     @Override
    public V borrowObject(K keythrows Exception {
        long starttime = System.currentTimeMillis();
        Latch<K, V> latch = new Latch<K, V>(key);
        byte whenExhaustedAction;
        long maxWait;
        synchronized (this) {
            // Get local copy of current config. Can't sync when used later as
            // it can result in a deadlock. Has the added advantage that config
            // is consistent for entire method execution
            whenExhaustedAction = ;
            maxWait = ;
            // Add this request to the queue
            .add(latch);
        }
        // Work the allocation queue, allocating idle instances and
        // instance creation permits in request arrival order
        allocate();
        for(;;) {
            synchronized (this) {
                assertOpen();
            }
            // If no object was allocated
            if (null == latch.getPair()) {
                // Check to see if we were allowed to create one
                if (latch.mayCreate()) {
                    // allow new object to be created
                } else {
                    // the pool is exhausted
                    switch(whenExhaustedAction) {
                        case :
                            // allow new object to be created
                            synchronized (this) {
                                // Make sure another thread didn't allocate us an object
                                // or permit a new object to be created
                                if (latch.getPair() == null && !latch.mayCreate()) {
                                    .remove(latch);
                                    latch.getPool().incrementInternalProcessingCount();
                                }
                            }
                        break;
                        case :
                            synchronized (this) {
                                // Make sure allocate hasn't already assigned an object
                                // in a different thread or permitted a new object to be created
                                if (latch.getPair() != null || latch.mayCreate()) {
                                    break;
                                }
                                .remove(latch);
                            }
                            throw new NoSuchElementException("Pool exhausted");
                        case :
                            try {
                                synchronized (latch) {
                                    // Before we wait, make sure another thread didn't allocate us an object
                                    // or permit a new object to be created
                                    if (latch.getPair() == null && !latch.mayCreate()) {
                                        if (maxWait <= 0) {
                                            latch.wait();
                                        } else {
                                            // this code may be executed again after a notify then continue cycle
                                            // so, need to calculate the amount of time to wait
                                            final long elapsed = (System.currentTimeMillis() - starttime);
                                            final long waitTime = maxWait - elapsed;
                                            if (waitTime > 0)
                                            {
                                                latch.wait(waitTime);
                                            }
                                        }
                                    } else {
                                        break;
                                    }
                                }
                                // see if we were awakened by a closing pool
                                if(isClosed() == true) {
                                    throw new IllegalStateException("Pool closed");
                                }
                            } catch(InterruptedException e) {
                                boolean doAllocate = false;
                                synchronized (this) {
                                    // Need to handle the all three possibilities
                                    if (latch.getPair() == null && !latch.mayCreate()) {
                                        // Case 1: latch still in allocation queue
                                        // Remove latch from the allocation queue
                                        .remove(latch);
                                    } else if (latch.getPair() == null && latch.mayCreate()) {
                                        // Case 2: latch has been given permission to create
                                        //         a new object
                                        latch.getPool().decrementInternalProcessingCount();
                                        doAllocate = true;
                                    } else {
                                        // Case 3: An object has been allocated
                                        latch.getPool().decrementInternalProcessingCount();
                                        latch.getPool().incrementActiveCount();
                                        returnObject(latch.getkey(), latch.getPair().getValue());
                                    }
                                }
                                if (doAllocate) {
                                    allocate();
                                }
                                Thread.currentThread().interrupt();
                                throw e;
                            }
                            if (maxWait > 0 && ((System.currentTimeMillis() - starttime) >= maxWait)) {
                                synchronized (this) {
                                    // Make sure allocate hasn't already assigned an object
                                    // in a different thread or permitted a new object to be created
                                    if (latch.getPair() == null && !latch.mayCreate()) {
                                        .remove(latch);
                                    } else {
                                        break;
                                    }
                                }
                                throw new NoSuchElementException("Timeout waiting for idle object");
                            } else {
                                continue// keep looping
                            }
                        default:
                            throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction +
                                    " not recognized.");
                    }
                }
            }
            boolean newlyCreated = false;
            if (null == latch.getPair()) {
                try {
                    V obj = .makeObject(key);
                    latch.setPair(new ObjectTimestampPair<V>(obj));
                    newlyCreated = true;
                } finally {
                    if (!newlyCreated) {
                        // object cannot be created
                        synchronized (this) {
                            latch.getPool().decrementInternalProcessingCount();
                            // No need to reset latch - about to throw exception
                        }
                        allocate();
                    }
                }
            }
            // activate & validate the object
            try {
                .activateObject(keylatch.getPair().);
                if ( && !.validateObject(keylatch.getPair().)) {
                    throw new Exception("ValidateObject failed");
                }
                synchronized (this) {
                    latch.getPool().decrementInternalProcessingCount();
                    latch.getPool().incrementActiveCount();
                }
                return latch.getPair().;
            } catch (Throwable e) {
                PoolUtils.checkRethrow(e);
                // object cannot be activated or is invalid
                try {
                    .destroyObject(keylatch.getPair().);
                } catch (Throwable e2) {
                    PoolUtils.checkRethrow(e2);
                    // cannot destroy broken object
                }
                synchronized (this) {
                    latch.getPool().decrementInternalProcessingCount();
                    if (!newlyCreated) {
                        latch.reset();
                        .add(0, latch);
                    }
                }
                allocate();
                if (newlyCreated) {
                    throw new NoSuchElementException(
                       "Could not create a validated object, cause: " +
                            e.getMessage());
                }
                else {
                    continue// keep looping
                }
            }
        }
    }

    
Allocate available instances to latches in the allocation queue. Then set _mayCreate to true for as many additional latches remaining in queue as _maxActive allows for each key. This method MUST NOT be called from inside a sync block.
    private void allocate() {
        boolean clearOldest = false;
        synchronized (this) {
            if (isClosed()) return;
            
            Iterator<Latch<K, V>> allocationQueueIter = .iterator();
            
            while (allocationQueueIter.hasNext()) {
                // First use any objects in the pool to clear the queue
                Latch<K, V> latch = allocationQueueIter.next();
                ObjectQueue pool = (.get(latch.getkey()));
                if (null == pool) {
                    pool = new ObjectQueue();
                    .put(latch.getkey(), pool);
                    .add(latch.getkey());
                }
                latch.setPool(pool);
                if (!pool.queue.isEmpty()) {
                    allocationQueueIter.remove();
                    latch.setPair(
                            pool.queue.removeFirst());
                    pool.incrementInternalProcessingCount();
                    --;
                    synchronized (latch) {
                        latch.notify();
                    }
                    // Next item in queue
                    continue;
                }
                // If there is a totalMaxActive and we are at the limit then
                // we have to make room
                if (( > 0) &&
                        ( +  +  >= )) {
                    clearOldest = true;
                    break;
                }
                // Second utilise any spare capacity to create new objects
                if (( < 0 || pool.activeCount + pool.internalProcessingCount < ) &&
                        ( < 0 ||  +  +  < )) {
                    // allow new object to be created
                    allocationQueueIter.remove();
                    latch.setMayCreate(true);
                    pool.incrementInternalProcessingCount();
                    synchronized (latch) {
                        latch.notify();
                    }
                    // Next item in queue
                    continue;
                }
                // If there is no per-key limit and we reach this point we
                // must have allocated all the objects we possibly can and there
                // is no point looking at the rest of the allocation queue
                if ( < 0) {
                    break;
                }
            }
        }
        
        if (clearOldest) {
            /* Clear oldest calls factory methods so it must be called from
             * outside the sync block.
             * It also needs to be outside the sync block as it calls
             * allocate(). If called inside the sync block, the call to
             * allocate() would be able to enter the sync block (since the
             * thread already has the lock) which may have unexpected,
             * unpleasant results.
             */
            clearOldest();
        }
    }
    
    
Clears any objects sitting idle in the pool by removing them from the idle instance pool and then invoking the configured PoolableObjectFactory's org.apache.commons.pool.KeyedPoolableObjectFactory.destroyObject(java.lang.Object,java.lang.Object) method on each idle instance.

Implementation notes:

  • This method does not destroy or effect in any way instances that are checked out when it is invoked.
  • Invoking this method does not prevent objects being returned to the idle instance pool, even during its execution. It locks the pool only during instance removal. Additional instances may be returned while removed items are being destroyed.
  • Exceptions encountered destroying idle instances are swallowed.
    @Override
    public void clear() {
        Map<K,  List<ObjectTimestampPair<V>>> toDestroy = new HashMap<K,  List<ObjectTimestampPair<V>>>();
        synchronized (this) {
            for (Iterator<K> it = .keySet().iterator(); it.hasNext();) {
                K key = it.next();
                ObjectQueue pool = .get(key);
                // Copy objects to new list so pool.queue can be cleared inside
                // the sync
                List<ObjectTimestampPair<V>> objects = new ArrayList<ObjectTimestampPair<V>>();
                objects.addAll(pool.queue);
                toDestroy.put(keyobjects);
                it.remove();
                .remove(key);
                 =  - pool.queue.size();
                 =
                     + pool.queue.size();
                pool.queue.clear();
            }
        }
        destroy(toDestroy);
    }

    
Clears oldest 15% of objects in pool. The method sorts the objects into a TreeMap and then iterates the first 15% for removal.

Since:
Pool 1.3
    public void clearOldest() {
        // Map of objects to destroy my key
        final Map<K, List<ObjectTimestampPair<V>>> toDestroy = new HashMap<K, List<ObjectTimestampPair<V>>>();
        // build sorted map of idle objects
        final Map<ObjectTimestampPair<V>, K> map = new TreeMap<ObjectTimestampPair<V>, K>();
        synchronized (this) {
            for (Iterator<K> keyiter = .keySet().iterator(); keyiter.hasNext();) {
                final K key = keyiter.next();
                final List<ObjectTimestampPair<V>> list = .get(key).;
                for (Iterator<ObjectTimestampPair<V>> it = list.iterator(); it.hasNext();) {
                    // each item into the map uses the objectimestamppair object
                    // as the key.  It then gets sorted based on the timstamp field
                    // each value in the map is the parent list it belongs in.
                    map.put(it.next(), key);
                }
            }
            // Now iterate created map and kill the first 15% plus one to account for zero
            Set<Entry<ObjectTimestampPair<V>, K>> setPairKeys = map.entrySet();
            int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
            Iterator<Entry<ObjectTimestampPair<V>, K>> iter = setPairKeys.iterator();
            while (iter.hasNext() && itemsToRemove > 0) {
                Entry<ObjectTimestampPair<V>, K> entry = iter.next();
                // kind of backwards on naming.  In the map, each key is the objecttimestamppair
                // because it has the ordering with the timestamp value.  Each value that the
                // key references is the key of the list it belongs to.
                K key = entry.getValue();
                ObjectTimestampPair<V> pairTimeStamp = entry.getKey();
                ObjectQueue objectQueue = .get(key);
                final List<ObjectTimestampPair<V>> list = objectQueue.queue;
                list.remove(pairTimeStamp);
                if (toDestroy.containsKey(key)) {
                    toDestroy.get(key).add(pairTimeStamp);
                } else {
                    List<ObjectTimestampPair<V>> listForKey = new ArrayList<ObjectTimestampPair<V>>();
                    listForKey.add(pairTimeStamp);
                    toDestroy.put(keylistForKey);
                }
                objectQueue.incrementInternalProcessingCount();
                --;
                itemsToRemove--;
            }
        }
        destroy(toDestroy);
    }

    
Clears the specified pool, removing all pooled instances corresponding to the given key.

Parameters:
key the key to clear
    @Override
    public void clear(K key) {
        Map<K, List<ObjectTimestampPair<V>>> toDestroy = new HashMap<K , List<ObjectTimestampPair<V>>>();
        final ObjectQueue pool;
        synchronized (this) {
            pool = .remove(key);
            if (pool == null) {
                return;
            } else {
                .remove(key);
            }
            // Copy objects to new list so pool.queue can be cleared inside
            // the sync
            List<ObjectTimestampPair<V>> objects = new ArrayList<ObjectTimestampPair<V>>();
            objects.addAll(pool.queue);
            toDestroy.put(keyobjects);
             =  - pool.queue.size();
             =
                 + pool.queue.size();
            pool.queue.clear();
        }
        destroy(toDestroy);
    }

    
Assuming Map<Object,Collection<ObjectTimestampPair>>, destroy all ObjectTimestampPair.value using the supplied factory.

Parameters:
m Map containing keyed pools to clear
factory KeyedPoolableObjectFactory used to destroy the objects
    private void destroy(Map<K,  List<ObjectTimestampPair<V>>> mKeyedPoolableObjectFactory<K, V> factory) {
        for (Iterator<Entry<K,  List<ObjectTimestampPair<V>>>> entries = m.entrySet().iterator(); entries.hasNext();) {
            Entry<K,  List<ObjectTimestampPair<V>>> entry = entries.next();
            K key = entry.getKey();
            List<ObjectTimestampPair<V>> c = entry.getValue();
            for (Iterator<ObjectTimestampPair<V>> it = c.iterator(); it.hasNext();) {
                try {
                    factory.destroyObject(
                            key,it.next().);
                } catch(Exception e) {
                    // ignore error, keep destroying the rest
                } finally {
                    synchronized(this) {
                        ObjectQueue objectQueue =
                                .get(key);
                        if (objectQueue != null) {
                            objectQueue.decrementInternalProcessingCount();
                            if (objectQueue.internalProcessingCount == 0 &&
                                    objectQueue.activeCount == 0 &&
                                    objectQueue.queue.isEmpty()) {
                                .remove(key);
                                .remove(key);
                            }
                        } else {
                            --;
                        }
                    }
                    allocate();
                }
            }
        }
    }

    
Returns the total number of instances current borrowed from this pool but not yet returned.

Returns:
the total number of instances currently borrowed from this pool
    @Override
    public synchronized int getNumActive() {
        return ;
    }

    
Returns the total number of instances currently idle in this pool.

Returns:
the total number of instances currently idle in this pool
    @Override
    public synchronized int getNumIdle() {
        return ;
    }

    
Returns the number of instances currently borrowed from but not yet returned to the pool corresponding to the given key.

Parameters:
key the key to query
Returns:
the number of instances corresponding to the given key currently borrowed in this pool
    @Override
    public synchronized int getNumActive(Object key) {
        final ObjectQueue pool = (.get(key));
        return pool != null ? pool.activeCount : 0;
    }

    
Returns the number of instances corresponding to the given key currently idle in this pool.

Parameters:
key the key to query
Returns:
the number of instances corresponding to the given key currently idle in this pool
    @Override
    public synchronized int getNumIdle(Object key) {
        final ObjectQueue pool = (.get(key));
        return pool != null ? pool.queue.size() : 0;
    }

    

Returns an object to a keyed pool.

For the pool to function correctly, the object instance must have been borrowed from the pool (under the same key) and not yet returned. Repeated returnObject calls on the same object/key pair (with no borrowObject calls in between) will result in multiple references to the object in the idle instance pool.

If maxIdle is set to a positive value and the number of idle instances under the given key has reached this value, the returning instance is destroyed.

If testOnReturn == true, the returning instance is validated before being returned to the idle instance pool under the given key. In this case, if validation fails, the instance is destroyed.

Parameters:
key pool key
obj instance to return to the keyed pool
Throws:
java.lang.Exception
    @Override
    public void returnObject(K key, V objthrows Exception {
        try {
            addObjectToPool(keyobjtrue);
        } catch (Exception e) {
            if ( != null) {
                try {
                    .destroyObject(keyobj);
                } catch (Exception e2) {
                    // swallowed
                }
                // TODO: Correctness here depends on control in addObjectToPool.
                // These two methods should be refactored, removing the
                // "behavior flag", decrementNumActive, from addObjectToPool.
                ObjectQueue pool = (.get(key));
                if (pool != null) {
                    synchronized(this) {
                        pool.decrementActiveCount();
                        if (pool.queue.isEmpty() &&
                                pool.activeCount == 0 &&
                                pool.internalProcessingCount == 0) {
                            .remove(key);
                            .remove(key);
                        }
                    }
                    allocate();
                }
            }
        }
    }

    

Adds an object to the keyed pool.

Validates the object if testOnReturn == true and passivates it before returning it to the pool. if validation or passivation fails, or maxIdle is set and there is no room in the pool, the instance is destroyed.

Calls allocate() on successful completion

Parameters:
key pool key
obj instance to add to the keyed pool
decrementNumActive whether or not to decrement the active count associated with the keyed pool
Throws:
java.lang.Exception
    private void addObjectToPool(K key, V obj,
            boolean decrementNumActivethrows Exception {
        // if we need to validate this object, do so
        boolean success = true// whether or not this object passed validation
        if ( && !.validateObject(keyobj)) {
            success = false;
        } else {
            .passivateObject(keyobj);
        }
        boolean shouldDestroy = !success;
        ObjectQueue pool;
        // Add instance to pool if there is room and it has passed validation
        // (if testOnreturn is set)
        boolean doAllocate = false;
        synchronized (this) {
            // grab the pool (list) of objects associated with the given key
            pool = .get(key);
            // if it doesn't exist, create it
            if (null == pool) {
                pool = new ObjectQueue();
                .put(keypool);
                .add(key);
            }
            if (isClosed()) {
                shouldDestroy = true;
            } else {
                // if there's no space in the pool, flag the object for destruction
                // else if we passivated successfully, return it to the pool
                if ( >= 0 && (pool.queue.size() >= )) {
                    shouldDestroy = true;
                } else if (success) {
                    // borrowObject always takes the first element from the queue,
                    // so for LIFO, push on top, FIFO add to end
                    if () {
                        pool.queue.addFirst(new ObjectTimestampPair<V>(obj));
                    } else {
                        pool.queue.addLast(new ObjectTimestampPair<V>(obj));
                    }
                    ++;
                    if (decrementNumActive) {
                        pool.decrementActiveCount();
                    }
                    doAllocate = true;
                }
            }
        }
        if (doAllocate) {
            allocate();
        }
        // Destroy the instance if necessary
        if (shouldDestroy) {
            try {
                .destroyObject(keyobj);
            } catch(Exception e) {
                // ignored?
            }
            // Decrement active count *after* destroy if applicable
            if (decrementNumActive) {
                synchronized(this) {
                    pool.decrementActiveCount();
                    if (pool.queue.isEmpty() &&
                            pool.activeCount == 0 &&
                            pool.internalProcessingCount == 0) {
                        .remove(key);
                        .remove(key);
                    }
                }
                allocate();
            }
        }
    }

    

Activation of this method decrements the active count associated with the given keyed pool and attempts to destroy obj.

Parameters:
key pool key
obj instance to invalidate
Throws:
java.lang.Exception if an exception occurs destroying the object
    @Override
    public void invalidateObject(K key, V objthrows Exception {
        try {
            .destroyObject(keyobj);
        } finally {
            synchronized (this) {
                ObjectQueue pool = (.get(key));
                if (null == pool) {
                    pool = new ObjectQueue();
                    .put(keypool);
                    .add(key);
                }
                pool.