You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2012/04/11 20:50:49 UTC

svn commit: r1324914 - in /commons/proper/pool/trunk/src: java/org/apache/commons/pool2/impl/ test/org/apache/commons/pool2/impl/

Author: markt
Date: Wed Apr 11 18:50:49 2012
New Revision: 1324914

URL: http://svn.apache.org/viewvc?rev=1324914&view=rev
Log:
Re-fix POOL-189 for trunk. Update and enable unit tests.

Modified:
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java?rev=1324914&r1=1324913&r2=1324914&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java Wed Apr 11 18:50:49 2012
@@ -226,7 +226,7 @@ public class GenericKeyedObjectPool<K,T>
     /**
      * Create a new <code>GenericKeyedObjectPool</code> using a specific
      * configuration.
-     * 
+     *
      * @param config    The configuration to use for this pool instance. The
      *                  configuration is used by value. Subsequent changes to
      *                  the configuration object will not be reflected in the
@@ -560,7 +560,7 @@ public class GenericKeyedObjectPool<K,T>
      * Sets the max number of objects to examine during each run of the
      * idle object evictor thread (if any).
      * <p>
-     * When a negative value is supplied, 
+     * When a negative value is supplied,
      * <code>ceil({@link #getNumIdle()})/abs({@link #getNumTestsPerEvictionRun})</code>
      * tests will be run.  I.e., when the value is <code>-n</code>, roughly one <code>n</code>th of the
      * idle objects will be tested per run.  When the value is positive, the number of tests
@@ -616,7 +616,7 @@ public class GenericKeyedObjectPool<K,T>
      * {@code minEvictableIdleTimeMillis} is positive, then
      * {@code softMinEvictableIdleTimeMillis} is ignored). The default setting
      * for this parameter is -1 (disabled).
-     * 
+     *
      * @return minimum amount of time an object may sit idle in the pool before
      *         it is eligible for eviction if minIdle instances are available
      * @since Pool 1.3
@@ -631,7 +631,7 @@ public class GenericKeyedObjectPool<K,T>
      * extra condition that at least "minIdle" object instances remain in the
      * pool. When non-positive, no objects will be evicted from the pool due to
      * idle time alone.
-     * 
+     *
      * @param softMinEvictableIdleTimeMillis
      *            minimum amount of time an object may sit idle in the pool
      *            before it is eligible for eviction.
@@ -669,7 +669,7 @@ public class GenericKeyedObjectPool<K,T>
                     evictionPolicyClassName, e);
         }
     }
-    
+
     /**
      * When <code>true</code>, objects will be
      * {@link org.apache.commons.pool2.PoolableObjectFactory#validateObject validated}
@@ -756,43 +756,43 @@ public class GenericKeyedObjectPool<K,T>
      /**
       * Obtain a reference to the factory used to create, destroy and validate
       * the objects used by this pool.
-      *  
+      *
       * @return the factory
       */
      public KeyedPoolableObjectFactory<K, T> getFactory() {
          return factory;
      }
-     
-     
+
+
     //-- ObjectPool methods ------------------------------------------
 
     /**
      * <p>Borrows an object from the keyed pool associated with the given key.</p>
-     * 
+     *
      * <p>If there is an idle instance available in the pool associated with the given key, then
      * either the most-recently returned (if {@link #getLifo() lifo} == true) or "oldest" (lifo == false)
      * instance sitting idle in the pool will be activated and returned.  If activation fails, or
      * {@link #getTestOnBorrow() 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.</p>
-     * 
+     *
      * <p>If there are no idle instances available in the pool associated with the given key, behavior
      * depends on the {@link #getMaxTotalPerKey() maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable)
      * {@link #getBlockWhenExhausted()} and {@link #getMaxWait() maxWait} settings. If the
      * number of instances checked out from the pool under the given key is less than <code>maxTotalPerKey</code> and
      * the total number of instances in circulation (under all keys) is less than <code>maxTotal</code>, a new instance
      * is created, activated and (if applicable) validated and returned to the caller.</p>
-     * 
+     *
      * <p>If the associated keyed pool is exhausted (no available idle instances and no capacity to create new ones),
      * this method will either block ({@link #getBlockWhenExhausted()} is true) or throw a <code>NoSuchElementException</code>
      * ({@link #getBlockWhenExhausted()} is false).
      * The length of time that this method will block when {@link #getBlockWhenExhausted()} is true
      * is determined by the {@link #getMaxWait() maxWait} property.</p>
-     * 
+     *
      * <p>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.</p>
-     * 
+     *
      * @param key pool key
      * @return object instance from the keyed pool
      * @throws NoSuchElementException if a keyed object instance cannot be returned.
@@ -801,12 +801,12 @@ public class GenericKeyedObjectPool<K,T>
     public T borrowObject(K key) throws Exception {
         return borrowObject(key, getMaxWait());
     }
-     
+
     /**
      * <p>Borrows an object from the keyed pool associated with the given key
      * using a user specific waiting time which only applies if
      * {@link #getBlockWhenExhausted()} is true.</p>
-     * 
+     *
      * @param key pool key
      * @param borrowMaxWait maximum amount of time to wait (in milliseconds)
      * @return object instance from the keyed pool
@@ -825,7 +825,7 @@ public class GenericKeyedObjectPool<K,T>
         boolean create;
         long waitTime = 0;
         ObjectDeque<T> objectDeque = register(key);
-        
+
         try {
             while (p == null) {
                 create = false;
@@ -869,7 +869,7 @@ public class GenericKeyedObjectPool<K,T>
                         p = null;
                     }
                 }
-    
+
                 if (p != null) {
                     try {
                         factory.activateObject(key, p.getObject());
@@ -916,7 +916,7 @@ public class GenericKeyedObjectPool<K,T>
         } finally {
             deregister(key);
         }
-        
+
         borrowedCount.incrementAndGet();
         synchronized (idleTimes) {
             idleTimes.add(Long.valueOf(p.getIdleTimeMillis()));
@@ -937,29 +937,29 @@ public class GenericKeyedObjectPool<K,T>
 
      /**
       * <p>Returns an object to a keyed pool.</p>
-      * 
+      *
       * <p>For the pool to function correctly, the object instance <strong>must</strong> have been borrowed
       * from the pool (under the same key) and not yet returned. Repeated <code>returnObject</code> calls on
       * the same object/key pair (with no <code>borrowObject</code> calls in between) will result in multiple
       * references to the object in the idle instance pool.</p>
-      * 
+      *
       * <p>If {@link #getMaxIdlePerKey() 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.</p>
-      * 
+      *
       * <p>If {@link #getTestOnReturn() 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.</p>
-      * 
+      *
       * @param key pool key
       * @param t instance to return to the keyed pool
       * @throws Exception
       */
      @Override
     public void returnObject(K key, T t) throws Exception {
-         
+
          ObjectDeque<T> objectDeque = poolMap.get(key);
-         
+
          PooledObject<T> p = objectDeque.getAllObjects().get(t);
-         
+
          if (p == null) {
              throw new IllegalStateException(
                      "Returned object not currently part of this pool");
@@ -1013,7 +1013,7 @@ public class GenericKeyedObjectPool<K,T>
                  idleObjects.addLast(p);
              }
          }
- 
+
          if (hasBorrowWaiters()) {
              reuseCapacity();
          }
@@ -1030,12 +1030,12 @@ public class GenericKeyedObjectPool<K,T>
          }
      }
 
-     
+
      /**
       * {@inheritDoc}
       * <p>Activation of this method decrements the active count associated with
       * the given keyed pool  and attempts to destroy <code>obj.</code></p>
-      * 
+      *
       * @param key pool key
       * @param obj instance to invalidate
       * @throws Exception if an exception occurs destroying the object
@@ -1044,9 +1044,9 @@ public class GenericKeyedObjectPool<K,T>
       */
      @Override
     public void invalidateObject(K key, T obj) throws Exception {
-         
+
          ObjectDeque<T> objectDeque = poolMap.get(key);
-         
+
          PooledObject<T> p = objectDeque.getAllObjects().get(obj);
          if (p == null) {
              throw new IllegalStateException(
@@ -1061,7 +1061,7 @@ public class GenericKeyedObjectPool<K,T>
       * idle instance pool and then invoking the configured PoolableObjectFactory's
       * {@link KeyedPoolableObjectFactory#destroyObject(Object, Object)} method on
       * each idle instance.
-      *  
+      *
       * <p> Implementation notes:
       * <ul><li>This method does not destroy or effect in any way instances that are
       * checked out when it is invoked.</li>
@@ -1074,7 +1074,7 @@ public class GenericKeyedObjectPool<K,T>
      @Override
     public void clear() {
          Iterator<K> iter = poolMap.keySet().iterator();
-         
+
          while (iter.hasNext()) {
              clear(iter.next());
          }
@@ -1089,15 +1089,15 @@ public class GenericKeyedObjectPool<K,T>
       */
      @Override
     public void clear(K key) {
-         
+
          ObjectDeque<T> objectDeque = register(key);
-         
+
          try {
              LinkedBlockingDeque<PooledObject<T>> idleObjects =
                      objectDeque.getIdleObjects();
-             
+
              PooledObject<T> p = idleObjects.poll();
-    
+
              while (p != null) {
                  try {
                      destroy(key, p, true);
@@ -1131,7 +1131,7 @@ public class GenericKeyedObjectPool<K,T>
     public int getNumIdle() {
          Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
          int result = 0;
-         
+
          while (iter.hasNext()) {
              result += iter.next().getIdleObjects().size();
          }
@@ -1175,9 +1175,9 @@ public class GenericKeyedObjectPool<K,T>
       * will fail with IllegalStateException, but {@link #returnObject(Object, Object)} and
       * {@link #invalidateObject(Object, Object)} will continue to work, with returned objects
       * destroyed on return.</p>
-      * 
-      * <p>Destroys idle instances in the pool by invoking {@link #clear()}.</p> 
-      * 
+      *
+      * <p>Destroys idle instances in the pool by invoking {@link #clear()}.</p>
+      *
       * @throws Exception
       */
      @Override
@@ -1192,15 +1192,25 @@ public class GenericKeyedObjectPool<K,T>
              }
 
              // Stop the evictor before the pool is closed since evict() calls
-             // assertOpen() 
+             // assertOpen()
              startEvictor(-1L);
 
              closed = true;
+             // This clear removes any idle objects
              clear();
              if (oname != null) {
                  ManagementFactory.getPlatformMBeanServer().unregisterMBean(
                          oname);
              }
+
+             // Release any threads that were waiting for an object
+             Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
+             while (iter.hasNext()) {
+                 iter.next().getIdleObjects().interuptTakeWaiters();
+             }
+             // This clear cleans up the keys now any waiting threads have been
+             // interrupted
+             clear();
          }
 
      }
@@ -1230,11 +1240,11 @@ public class GenericKeyedObjectPool<K,T>
      /** Whether or not the pool is closed */
      private volatile boolean closed = false;
 
-     
+
      /**
       * 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() {
@@ -1278,25 +1288,25 @@ public class GenericKeyedObjectPool<K,T>
             }
         }
     }
-    
+
     /**
      * Attempt to create one new instance to serve from the most heavily
      * loaded pool that can add a new instance.
-     * 
+     *
      * This method exists to ensure liveness in the pool when threads are
      * parked waiting and capacity to create instances under the requested keys
      * subsequently becomes available.
-     * 
+     *
      * This method is not guaranteed to create an instance and its selection
      * of the most loaded pool that can create an instance may not always be
      * correct, since it does not lock the pool and instances may be created,
      * borrowed, returned or destroyed by other threads while it is executing.
-     * 
+     *
      * @return true if an instance is created and added to a pool
      */
     private boolean reuseCapacity() {
         final int maxTotalPerKey = getMaxTotalPerKey();
-   
+
         // Find the most loaded pool that could take a new instance
         int maxQueueLength = 0;
         LinkedBlockingDeque<PooledObject<T>> mostLoaded = null;
@@ -1308,12 +1318,12 @@ public class GenericKeyedObjectPool<K,T>
                 final int queueLength = pool.getTakeQueueLength();
                 if (getNumActive(k) < maxTotalPerKey && queueLength > maxQueueLength) {
                     maxQueueLength = queueLength;
-                    mostLoaded = pool; 
+                    mostLoaded = pool;
                     loadedKey = k;
                 }
             }
         }
-        
+
         // Attempt to add an instance to the most loaded pool
         boolean success = false;
         if (mostLoaded != null) {
@@ -1330,13 +1340,13 @@ public class GenericKeyedObjectPool<K,T>
                 deregister(loadedKey);
             }
         }
-        return success;   
+        return success;
     }
-    
+
     /**
      * Returns true if there are threads parked waiting to borrow instances
      * from at least one of the keyed pools.
-     * 
+     *
      * @return true if {@link #reuseCapacity()} would be useful
      */
     private boolean hasBorrowWaiters() {
@@ -1382,11 +1392,11 @@ public class GenericKeyedObjectPool<K,T>
                     getMinEvictableIdleTimeMillis(),
                     getSoftMinEvictableIdleTimeMillis(),
                     getMinIdlePerKey());
-            
+
             boolean testWhileIdle = getTestWhileIdle();
-            
+
             LinkedBlockingDeque<PooledObject<T>> idleObjects = null;
-             
+
             for (int i = 0, m = getNumTests(); i < m; i++) {
                 if(evictionIterator == null || !evictionIterator.hasNext()) {
                     if (evictionKeyIterator == null ||
@@ -1408,7 +1418,7 @@ public class GenericKeyedObjectPool<K,T>
                             continue;
                         }
                         idleObjects = objectDeque.getIdleObjects();
-                        
+
                         if (getLifo()) {
                             evictionIterator = idleObjects.descendingIterator();
                         } else {
@@ -1433,14 +1443,14 @@ public class GenericKeyedObjectPool<K,T>
                     evictionIterator = null;
                     continue;
                 }
-    
+
                 if (!underTest.startEvictionTest()) {
                     // Object was borrowed in another thread
                     // Don't count this as an eviction test so reduce i;
                     i--;
                     continue;
                 }
-    
+
                 if (evictionPolicy.evict(evictionConfig, underTest,
                         poolMap.get(evictionKey).getIdleObjects().size())) {
                     destroy(evictionKey, underTest, true);
@@ -1449,7 +1459,7 @@ public class GenericKeyedObjectPool<K,T>
                     if (testWhileIdle) {
                         boolean active = false;
                         try {
-                            factory.activateObject(evictionKey, 
+                            factory.activateObject(evictionKey,
                                     underTest.getObject());
                             active = true;
                         } catch (Exception e) {
@@ -1481,14 +1491,14 @@ public class GenericKeyedObjectPool<K,T>
         }
     }
 
-     
+
     private PooledObject<T> create(K key) throws Exception {
         int maxTotalPerKey = getMaxTotalPerKey(); // Per key
         int maxTotal = getMaxTotal();   // All keys
 
         // Check against the overall limit
         boolean loop = true;
-        
+
         while (loop) {
             int newNumTotal = numTotal.incrementAndGet();
             if (maxTotal > -1 && newNumTotal > maxTotal) {
@@ -1502,7 +1512,7 @@ public class GenericKeyedObjectPool<K,T>
                 loop = false;
             }
         }
-         
+
         ObjectDeque<T> objectDeque = poolMap.get(key);
         long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
 
@@ -1513,7 +1523,7 @@ public class GenericKeyedObjectPool<K,T>
             objectDeque.getCreateCount().decrementAndGet();
             return null;
         }
-         
+
 
         T t = null;
         try {
@@ -1532,7 +1542,7 @@ public class GenericKeyedObjectPool<K,T>
     /**
      * Invalidate toDestroy and if it is idle under key or always is true, destroy it.
      * Return true if toDestroy is destroyed.
-     * 
+     *
      * @param key pool key
      * @param toDestroy instance to invalidate and destroy if conditions are met
      * @param always true means instance will be destroyed regardless of idle pool membership
@@ -1541,16 +1551,16 @@ public class GenericKeyedObjectPool<K,T>
      */
     private boolean destroy(K key, PooledObject<T> toDestroy, boolean always)
             throws Exception {
-        
+
         ObjectDeque<T> objectDeque = register(key);
 
         try {
             boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy);
-            
+
             if (isIdle || always) {
                 objectDeque.getAllObjects().remove(toDestroy.getObject());
                 toDestroy.invalidate();
-        
+
                 try {
                     factory.destroyObject(key, toDestroy.getObject());
                 } finally {
@@ -1570,7 +1580,7 @@ public class GenericKeyedObjectPool<K,T>
     /**
      * Registers a new key in the {@link poolMap} and {@link poolKeyList}
      * and returns the key queue details.
-     * If the key is already in the map, increments the interest count and 
+     * If the key is already in the map, increments the interest count and
      * returns the existing details.
      * <p>
      * register and deregister must be used as a pair.
@@ -1609,14 +1619,14 @@ public class GenericKeyedObjectPool<K,T>
         }
         return objectDeque;
     }
-    
+
     /**
      * Deregisters an unused key from {@link poolMap} and {@link poolKeyList}.
      * Fetches the key and decrements the interest count; if this is zero,
      * and the number of managed instances is zero, then the key is removed.
      * <p>
      * register and deregister must be used as a pair.
-     * 
+     *
      * @param k the key to deregister
      * @throws NullPointerException if the key is not in the {@link poolMap}
      * @see #register(Object)
@@ -1697,16 +1707,16 @@ public class GenericKeyedObjectPool<K,T>
         }
     }
 
-    
+
     /**
      * <p>Adds an object to the keyed pool.</p>
-     * 
+     *
      * <p>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.</p>
-     * 
+     *
      * <p>Calls {@link #allocate()} on successful completion</p>
-     * 
+     *
      * @param key pool key
      * @param p instance to add to the keyed pool
      * @throws Exception
@@ -1789,7 +1799,7 @@ public class GenericKeyedObjectPool<K,T>
     /**
      * Returns pool info including {@link #getNumActive()}, {@link #getNumIdle()}
      * and currently defined keys.
-     * 
+     *
      * @return string containing debug information
      */
     String debugInfo() {
@@ -1805,11 +1815,11 @@ public class GenericKeyedObjectPool<K,T>
         return buf.toString();
     }
 
-    /** 
+    /**
      * Returns the number of tests to be performed in an Evictor run,
      * based on the current values of <code>_numTestsPerEvictionRun</code>
      * and <code>_totalIdle</code>.
-     * 
+     *
      * @see #setNumTestsPerEvictionRun
      * @return the number of tests for the Evictor to run
      */
@@ -1826,12 +1836,12 @@ public class GenericKeyedObjectPool<K,T>
      * This returns the number of objects to create during the pool
      * sustain cycle. This will ensure that the minimum number of idle
      * instances is maintained without going past the maxTotalPerKey value.
-     * 
+     *
      * @param pool the ObjectPool to calculate the deficit for
      * @return The number of objects to be created
      */
     private int calculateDeficit(ObjectDeque<T> objectDeque) {
-        
+
         if (objectDeque == null) {
             return getMinIdlePerKey();
         }
@@ -1860,7 +1870,7 @@ public class GenericKeyedObjectPool<K,T>
         return objectDefecit;
     }
 
-    
+
     //--- JMX specific attributes ----------------------------------------------
 
     private void initStats() {
@@ -1964,30 +1974,30 @@ public class GenericKeyedObjectPool<K,T>
      * Return an estimate of the number of threads currently blocked waiting for
      * an object from the pool. This is intended for monitoring only, not for
      * synchronization control.
-     * 
+     *
      * @return  An estimate of the number of threads currently blocked waiting
-     *          for an object from the pool 
+     *          for an object from the pool
      */
     public int getNumWaiters() {
         int result = 0;
-        
+
         if (getBlockWhenExhausted()) {
             Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
-            
+
             while (iter.hasNext()) {
                 // Assume no overflow
                 result += iter.next().getIdleObjects().getTakeQueueLength();
             }
         }
-        
+
         return result;
     }
-    
+
     /**
      * Return an estimate of the number of threads currently blocked waiting for
      * an object from the pool for the given key. This is intended for
      * monitoring only, not for synchronization control.
-     * 
+     *
      * @return  An estimate of the number of threads currently blocked waiting
      *          for an object from the pool for the given key
      */
@@ -2014,7 +2024,7 @@ public class GenericKeyedObjectPool<K,T>
         private final LinkedBlockingDeque<PooledObject<S>> idleObjects =
                 new LinkedBlockingDeque<PooledObject<S>>();
 
-        /** 
+        /**
          * Number of instances created - number destroyed.
          * Invariant: createCount <= maxTotalPerKey
          */
@@ -2024,51 +2034,51 @@ public class GenericKeyedObjectPool<K,T>
         private final Map<S, PooledObject<S>> allObjects =
                 new ConcurrentHashMap<S, PooledObject<S>>();
 
-        /** 
-         * Number of threads with registered interest in this key. 
+        /**
+         * Number of threads with registered interest in this key.
          * register(K) increments this counter and deRegister(K) decrements it.
          * Invariant: empty keyed pool will not be dropped unless numInterested is 0.
          */
         private final AtomicLong numInterested = new AtomicLong(0);
-        
+
         /**
          * Returns the idle instance pool.
-         * 
+         *
          * @return deque of idle instances
          */
         public LinkedBlockingDeque<PooledObject<S>> getIdleObjects() {
             return idleObjects;
         }
-        
+
         /**
          * Returns the number of instances that have been created under this
          * this key minus the number that have been destroyed.
-         * 
+         *
          * @return the number of instances (active or idle) currently being
          * managed by the pool under this key
          */
         public AtomicInteger getCreateCount() {
             return createCount;
         }
-        
+
         /**
          * Returns the number of threads with registered interest in this key.
          * This keyed pool will not be dropped if empty unless this method returns 0.
-         * 
+         *
          * @return number of threads that have registered, but not deregistered this key
          */
         public AtomicLong getNumInterested() {
             return numInterested;
         }
-        
+
         /**
          * The full set of objects under management by this keyed pool.
-         * 
+         *
          * Includes both idle instances and those checked out to clients.
          * The map is keyed on pooled instances.  Note: pooled instances
          * <em>must</em> be distinguishable by equals for this structure to
          * work properly.
-         * 
+         *
          * @return map of pooled instances
          */
         public Map<S, PooledObject<S>> getAllObjects() {
@@ -2095,7 +2105,7 @@ public class GenericKeyedObjectPool<K,T>
                 //  set the class loader for the factory
                 Thread.currentThread().setContextClassLoader(
                         factoryClassLoader);
-                
+
                 //Evict from the pool
                 try {
                     evict();
@@ -2267,13 +2277,13 @@ public class GenericKeyedObjectPool<K,T>
      * extra condition that at least "minIdle" amount of object remain in the
      * pool. When non-positive, no objects will be evicted from the pool due to
      * idle time alone.
-     * 
+     *
      * @see #setSoftMinEvictableIdleTimeMillis
      * @see #getSoftMinEvictableIdleTimeMillis
      */
     private volatile long softMinEvictableIdleTimeMillis =
         GenericKeyedObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
-    
+
     /** Whether or not the pools behave as LIFO queues (last in first out) */
     private boolean lifo = GenericKeyedObjectPoolConfig.DEFAULT_LIFO;
 
@@ -2294,7 +2304,7 @@ public class GenericKeyedObjectPool<K,T>
      */
     private final Map<K,ObjectDeque<T>> poolMap =
             new ConcurrentHashMap<K,ObjectDeque<T>>(); // @GuardedBy("keyLock") for write access (and some read access)
-    
+
     /**
      * List of pool keys - used to control eviction order. The list of keys
      * <b>must</b> be kept in step with {@link #poolMap} using {@link #keyLock}
@@ -2313,7 +2323,7 @@ public class GenericKeyedObjectPool<K,T>
      * created at any one time.
      */
     private final AtomicInteger numTotal = new AtomicInteger(0);
-    
+
     /**
      * My idle object eviction {@link TimerTask}, if any.
      */
@@ -2329,7 +2339,7 @@ public class GenericKeyedObjectPool<K,T>
      * An iterator for {@link #poolMap} entries.
      */
     private Iterator<K> evictionKeyIterator = null; // @GuardedBy("evictionLock") - except close()
-    
+
     /**
      * The key associated with the {@link ObjectDeque#getIdleObjects()}
      * currently being evicted.
@@ -2340,8 +2350,8 @@ public class GenericKeyedObjectPool<K,T>
      * Policy that determines if an object is eligible for eviction or not.
      */
     private EvictionPolicy<T> evictionPolicy;
-    
-    /** Object used to ensure thread safety of eviction process */ 
+
+    /** Object used to ensure thread safety of eviction process */
     private final Object evictionLock = new Object();
 
     /** Object used to ensure closed() is only called once. */

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1324914&r1=1324913&r2=1324914&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java Wed Apr 11 18:50:49 2012
@@ -163,7 +163,7 @@ import org.apache.commons.pool2.Poolable
  * 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.
- * 
+ *
  * @see GenericKeyedObjectPool
  * @param <T>
  *            Type of element pooled in this pool.
@@ -191,7 +191,7 @@ public class GenericObjectPool<T> extend
         this.factory = factory;
         // save the current CCL to be used later by the evictor Thread
         factoryClassLoader = Thread.currentThread().getContextClassLoader();
-        
+
         setConfig(config);
 
         startEvictor(getTimeBetweenEvictionRunsMillis());
@@ -248,7 +248,7 @@ public class GenericObjectPool<T> extend
      * (checked out to clients, or idle awaiting checkout) at a given time. When
      * non-positive, there is no limit to the number of objects that can be
      * managed by the pool at one time.
-     * 
+     *
      * @return the cap on the total number of object instances managed by the
      *         pool.
      * @see #setMaxTotal
@@ -262,7 +262,7 @@ public class GenericObjectPool<T> extend
      * Sets the cap on the number of objects that can be allocated by the pool
      * (checked out to clients, or idle awaiting checkout) at a given time. Use
      * a negative value for no limit.
-     * 
+     *
      * @param maxTotal
      *            The cap on the total number of object instances managed by the
      *            pool. Negative values mean that there is no limit to the
@@ -277,7 +277,7 @@ public class GenericObjectPool<T> extend
      * Returns whether to block when the {@link #borrowObject} method is
      * invoked when the pool is exhausted (the maximum number of "active"
      * objects has been reached).
-     * 
+     *
      * @return true if should block when the pool is exhuasted
      * @see #setBlockWhenExhausted
      */
@@ -290,7 +290,7 @@ public class GenericObjectPool<T> extend
      * Sets whether to block when the {@link #borrowObject} method is invoked
      * when the pool is exhausted (the maximum number of "active" objects has
      * been reached).
-     * 
+     *
      * @param blockWhenExhausted   true if should block when the pool is exhausted
      * @see #getBlockWhenExhausted
      */
@@ -303,7 +303,7 @@ public class GenericObjectPool<T> extend
      * {@link #borrowObject} method should block before throwing an exception
      * when the pool is exhausted and the {@link #getBlockWhenExhausted} is true.
      * When less than 0, the {@link #borrowObject} method may block indefinitely.
-     * 
+     *
      * @return maximum number of milliseconds to block when borrowing an object.
      * @see #setMaxWait
      * @see #setBlockWhenExhausted
@@ -318,7 +318,7 @@ public class GenericObjectPool<T> extend
      * {@link #borrowObject} method should block before throwing an exception
      * when the pool is exhausted and the {@link #getBlockWhenExhausted} is true.
      * When less than 0, the {@link #borrowObject} method may block indefinitely.
-     * 
+     *
      * @param maxWait
      *            maximum number of milliseconds to block when borrowing an
      *            object.
@@ -331,7 +331,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * Returns the cap on the number of "idle" instances in the pool.
-     * 
+     *
      * @return the cap on the number of "idle" instances in the pool.
      * @see #setMaxIdle
      */
@@ -348,7 +348,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @param maxIdle
      *            The cap on the number of "idle" instances in the pool. Use a
      *            negative value to indicate an unlimited number of idle
@@ -365,7 +365,7 @@ public class GenericObjectPool<T> extend
      * when <code>numActive + numIdle >= maxActive.</code> This setting has no
      * effect if the idle object evictor is disabled (i.e. if
      * <code>timeBetweenEvictionRunsMillis <= 0</code>).
-     * 
+     *
      * @param minIdle
      *            The minimum number of objects.
      * @see #getMinIdle
@@ -379,7 +379,7 @@ public class GenericObjectPool<T> extend
      * Returns the minimum number of objects allowed in the pool before the
      * evictor thread (if active) spawns new objects. (Note no objects are
      * created when: numActive + numIdle >= maxActive)
-     * 
+     *
      * @return The minimum number of objects.
      * @see #setMinIdle
      */
@@ -394,7 +394,7 @@ public class GenericObjectPool<T> extend
      * returned by the {@link #borrowObject} method. If the object fails to
      * validate, it will be dropped from the pool, and we will attempt to borrow
      * another.
-     * 
+     *
      * @return <code>true</code> if objects are validated before being borrowed.
      * @see #setTestOnBorrow
      */
@@ -409,7 +409,7 @@ public class GenericObjectPool<T> extend
      * returned by the {@link #borrowObject} method. If the object fails to
      * validate, it will be dropped from the pool, and we will attempt to borrow
      * another.
-     * 
+     *
      * @param testOnBorrow
      *            <code>true</code> if objects should be validated before being
      *            borrowed.
@@ -423,7 +423,7 @@ public class GenericObjectPool<T> extend
      * When <tt>true</tt>, objects will be
      * {@link PoolableObjectFactory#validateObject validated} before being
      * returned to the pool within the {@link #returnObject}.
-     * 
+     *
      * @return <code>true</code> when objects will be validated after returned
      *         to {@link #returnObject}.
      * @see #setTestOnReturn
@@ -437,7 +437,7 @@ public class GenericObjectPool<T> extend
      * When <tt>true</tt>, objects will be
      * {@link PoolableObjectFactory#validateObject validated} before being
      * returned to the pool within the {@link #returnObject}.
-     * 
+     *
      * @param testOnReturn
      *            <code>true</code> so objects will be validated after returned
      *            to {@link #returnObject}.
@@ -451,7 +451,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @return number of milliseconds to sleep between evictor runs.
      * @see #setTimeBetweenEvictionRunsMillis
      */
@@ -464,7 +464,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @param timeBetweenEvictionRunsMillis
      *            number of milliseconds to sleep between evictor runs.
      * @see #getTimeBetweenEvictionRunsMillis
@@ -478,7 +478,7 @@ public class GenericObjectPool<T> extend
     /**
      * Returns the max number of objects to examine during each run of the idle
      * object evictor thread (if any).
-     * 
+     *
      * @return max number of objects to examine during each evictor run.
      * @see #setNumTestsPerEvictionRun
      * @see #setTimeBetweenEvictionRunsMillis
@@ -498,7 +498,7 @@ public class GenericObjectPool<T> extend
      * <i>n</i>th 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 pool.
-     * 
+     *
      * @param numTestsPerEvictionRun
      *            max number of objects to examine during each evictor run.
      * @see #getNumTestsPerEvictionRun
@@ -511,7 +511,7 @@ public class GenericObjectPool<T> extend
     /**
      * 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).
-     * 
+     *
      * @return minimum amount of time an object may sit idle in the pool before
      *         it is eligible for eviction.
      * @see #setMinEvictableIdleTimeMillis
@@ -527,7 +527,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @param minEvictableIdleTimeMillis
      *            minimum amount of time an object may sit idle in the pool
      *            before it is eligible for eviction.
@@ -549,7 +549,7 @@ public class GenericObjectPool<T> extend
      * {@code minEvictableIdleTimeMillis} is positive, then
      * {@code softMinEvictableIdleTimeMillis} is ignored). The default setting
      * for this parameter is -1 (disabled).
-     * 
+     *
      * @return minimum amount of time an object may sit idle in the pool before
      *         it is eligible for eviction if minIdle instances are available
      * @since Pool 1.3
@@ -564,7 +564,7 @@ public class GenericObjectPool<T> extend
      * extra condition that at least "minIdle" object instances remain in the
      * pool. When non-positive, no objects will be evicted from the pool due to
      * idle time alone.
-     * 
+     *
      * @param softMinEvictableIdleTimeMillis
      *            minimum amount of time an object may sit idle in the pool
      *            before it is eligible for eviction.
@@ -608,7 +608,7 @@ public class GenericObjectPool<T> extend
      * {@link PoolableObjectFactory#validateObject validated} by the idle object
      * evictor (if any). If an object fails to validate, it will be dropped from
      * the pool.
-     * 
+     *
      * @return <code>true</code> when objects will be validated by the evictor.
      * @see #setTestWhileIdle
      * @see #setTimeBetweenEvictionRunsMillis
@@ -623,7 +623,7 @@ public class GenericObjectPool<T> extend
      * {@link PoolableObjectFactory#validateObject validated} by the idle object
      * evictor (if any). If an object fails to validate, it will be dropped from
      * the pool.
-     * 
+     *
      * @param testWhileIdle
      *            <code>true</code> so objects will be validated by the evictor.
      * @see #getTestWhileIdle
@@ -639,7 +639,7 @@ public class GenericObjectPool<T> extend
      * the pool (if there are idle instances available). False means that the
      * pool behaves as a FIFO queue - objects are taken from the idle object
      * pool in the order that they are returned to the pool.
-     * 
+     *
      * @return <code>true</true> if the pool is configured to act as a LIFO queue
      * @since 1.4
      */
@@ -654,7 +654,7 @@ public class GenericObjectPool<T> extend
      * idle instances available). False means that the pool behaves as a FIFO
      * queue - objects are taken from the idle object pool in the order that
      * they are returned to the pool.
-     * 
+     *
      * @param lifo
      *            the new value for the LIFO property
      * @since 1.4
@@ -665,7 +665,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * Sets my configuration.
-     * 
+     *
      * @param conf
      *            configuration to use.
      * @see GenericObjectPoolConfig
@@ -692,7 +692,7 @@ public class GenericObjectPool<T> extend
     /**
      * Obtain a reference to the factory used to create, destroy and validate
      * the objects used by this pool.
-     *  
+     *
      * @return the factory
      */
     public PoolableObjectFactory<T> getFactory() {
@@ -739,7 +739,7 @@ public class GenericObjectPool<T> extend
      * pool 1.5, a "fairness" algorithm has been implemented to ensure that
      * threads receive available instances in request arrival order.
      * </p>
-     * 
+     *
      * @return object instance
      * @throws NoSuchElementException
      *             if an instance cannot be returned
@@ -748,11 +748,11 @@ public class GenericObjectPool<T> extend
     public T borrowObject() throws Exception {
         return borrowObject(getMaxWait());
     }
-    
+
     /**
      * Borrow an object from the pool using a user specific waiting time which
      * only applies if {@link #getBlockWhenExhausted()} is true.
-     * 
+     *
      * @param borrowMaxWait The time to wait in milliseconds for an object to
      *                      become available
      * @return object instance
@@ -885,7 +885,7 @@ public class GenericObjectPool<T> extend
      * instance is validated before being returned to the idle instance pool. In
      * this case, if validation fails, the instance is destroyed.
      * </p>
-     * 
+     *
      * @param obj
      *            instance to return to the pool
      */
@@ -961,7 +961,7 @@ public class GenericObjectPool<T> extend
      * Activation of this method decrements the active count and attempts to
      * destroy the instance.
      * </p>
-     * 
+     *
      * @throws Exception if the configured {@link PoolableObjectFactory} throws an
      * exception destroying obj
      * @throws IllegalStateException if obj does not belong to this pool
@@ -1010,7 +1010,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * Return the number of instances currently borrowed from this pool.
-     * 
+     *
      * @return the number of instances currently borrowed from this pool
      */
     @Override
@@ -1020,7 +1020,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * Return the number of instances currently idle in this pool.
-     * 
+     *
      * @return the number of instances currently idle in this pool
      */
     @Override
@@ -1038,7 +1038,7 @@ public class GenericObjectPool<T> extend
      * <p>
      * Destroys idle instances in the pool by invoking {@link #clear()}.
      * </p>
-     * 
+     *
      * @throws Exception
      */
     @Override
@@ -1053,7 +1053,7 @@ public class GenericObjectPool<T> extend
             }
 
             // Stop the evictor before the pool is closed since evict() calls
-            // assertOpen() 
+            // assertOpen()
             startEvictor(-1L);
 
             super.close();
@@ -1062,6 +1062,9 @@ public class GenericObjectPool<T> extend
                 ManagementFactory.getPlatformMBeanServer().unregisterMBean(
                         oname);
             }
+
+            // Release any threads that were waiting for an object
+            idleObjects.interuptTakeWaiters();
         }
     }
 
@@ -1077,7 +1080,7 @@ public class GenericObjectPool<T> extend
      * Successive activations of this method examine objects in in sequence,
      * cycling through objects in oldest-to-youngest order.
      * </p>
-     * 
+     *
      * @throws Exception
      *             if the pool is closed or eviction fails.
      */
@@ -1095,9 +1098,9 @@ public class GenericObjectPool<T> extend
                     getMinEvictableIdleTimeMillis(),
                     getSoftMinEvictableIdleTimeMillis(),
                     getMinIdle());
-            
+
             boolean testWhileIdle = getTestWhileIdle();
-                    
+
             for (int i = 0, m = getNumTests(); i < m; i++) {
                 if (evictionIterator == null || !evictionIterator.hasNext()) {
                     if (getLifo()) {
@@ -1110,7 +1113,7 @@ public class GenericObjectPool<T> extend
                     // Pool exhausted, nothing to do here
                     return;
                 }
-    
+
                 try {
                     underTest = evictionIterator.next();
                 } catch (NoSuchElementException nsee) {
@@ -1120,14 +1123,14 @@ public class GenericObjectPool<T> extend
                     evictionIterator = null;
                     continue;
                 }
-    
+
                 if (!underTest.startEvictionTest()) {
                     // Object was borrowed in another thread
                     // Don't count this as an eviction test so reduce i;
                     i--;
                     continue;
                 }
-    
+
                 if (evictionPolicy.evict(evictionConfig, underTest,
                         idleObjects.size())) {
                     destroy(underTest);
@@ -1203,7 +1206,7 @@ public class GenericObjectPool<T> extend
     /**
      * Check to see if we are below our minimum number of objects if so enough
      * to bring us back to our minimum.
-     * 
+     *
      * @throws Exception
      *             when {@link #addObject()} fails.
      */
@@ -1259,7 +1262,7 @@ public class GenericObjectPool<T> extend
     /**
      * Start the eviction thread or service, or when <i>delay</i> is
      * non-positive, stop it if it is already running.
-     * 
+     *
      * @param delay
      *            milliseconds between evictor runs.
      */
@@ -1282,7 +1285,7 @@ public class GenericObjectPool<T> extend
      * Returns pool info including {@link #getNumActive()},
      * {@link #getNumIdle()} and a list of objects idle in the pool with their
      * idle times.
-     * 
+     *
      * @return string containing debug information
      */
     String debugInfo() {
@@ -1300,7 +1303,7 @@ public class GenericObjectPool<T> extend
      * Returns the number of tests to be performed in an Evictor run, based on
      * the current value of <code>numTestsPerEvictionRun</code> and the number
      * of idle instances in the pool.
-     * 
+     *
      * @see #setNumTestsPerEvictionRun
      * @return the number of tests for the Evictor to run
      */
@@ -1397,9 +1400,9 @@ public class GenericObjectPool<T> extend
      * Return an estimate of the number of threads currently blocked waiting for
      * an object from the pool. This is intended for monitoring only, not for
      * synchronization control.
-     * 
+     *
      * @return  An estimate of the number of threads currently blocked waiting
-     *          for an object from the pool 
+     *          for an object from the pool
      */
     public int getNumWaiters() {
         if (getBlockWhenExhausted()) {
@@ -1413,7 +1416,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * The idle object evictor {@link TimerTask}.
-     * 
+     *
      * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
      */
     private class Evictor extends TimerTask {
@@ -1457,7 +1460,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * The cap on the number of idle instances in the pool.
-     * 
+     *
      * @see #setMaxIdle
      * @see #getMaxIdle
      */
@@ -1465,7 +1468,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * The cap on the minimum number of idle instances in the pool.
-     * 
+     *
      * @see #setMinIdle
      * @see #getMinIdle
      */
@@ -1473,7 +1476,7 @@ public class GenericObjectPool<T> extend
 
     /**
      * The cap on the total number of active instances from the pool.
-     * 
+     *
      * @see #setMaxTotal
      * @see #getMaxTotal
      */
@@ -1486,7 +1489,7 @@ public class GenericObjectPool<T> extend
      * {@link #getBlockWhenExhausted()} is true.
      * When less than 0, the
      * {@link #borrowObject} method may block indefinitely.
-     * 
+     *
      * @see #setMaxWait
      * @see #getMaxWait
      * @see #setBlockWhenExhausted
@@ -1498,7 +1501,7 @@ public class GenericObjectPool<T> extend
      * When the {@link #borrowObject} method is invoked when the pool is
      * exhausted (the maximum number of "active" objects has been reached)
      * should the {@link #borrowObject} method block or not?
-     * 
+     *
      * @see #setBlockWhenExhausted
      * @see #getBlockWhenExhausted
      */
@@ -1511,7 +1514,7 @@ public class GenericObjectPool<T> extend
      * returned by the {@link #borrowObject} method. If the object fails to
      * validate, it will be dropped from the pool, and we will attempt to borrow
      * another.
-     * 
+     *
      * @see #setTestOnBorrow
      * @see #getTestOnBorrow
      */
@@ -1522,7 +1525,7 @@ public class GenericObjectPool<T> extend
      * When <tt>true</tt>, objects will be
      * {@link PoolableObjectFactory#validateObject validated} before being
      * returned to the pool within the {@link #returnObject}.
-     * 
+     *
      * @see #getTestOnReturn
      * @see #setTestOnReturn
      */
@@ -1534,7 +1537,7 @@ public class GenericObjectPool<T> extend
      * {@link PoolableObjectFactory#validateObject validated} by the idle object
      * evictor (if any). If an object fails to validate, it will be dropped from
      * the pool.
-     * 
+     *
      * @see #setTestWhileIdle
      * @see #getTestWhileIdle
      * @see #getTimeBetweenEvictionRunsMillis
@@ -1547,7 +1550,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @see #setTimeBetweenEvictionRunsMillis
      * @see #getTimeBetweenEvictionRunsMillis
      */
@@ -1562,7 +1565,7 @@ public class GenericObjectPool<T> extend
      * <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
      * tests will be run. I.e., when the value is <i>-n</i>, roughly one
      * <i>n</i>th of the idle objects will be tested per run.
-     * 
+     *
      * @see #setNumTestsPerEvictionRun
      * @see #getNumTestsPerEvictionRun
      * @see #getTimeBetweenEvictionRunsMillis
@@ -1576,7 +1579,7 @@ public class GenericObjectPool<T> extend
      * 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.
-     * 
+     *
      * @see #setMinEvictableIdleTimeMillis
      * @see #getMinEvictableIdleTimeMillis
      * @see #getTimeBetweenEvictionRunsMillis
@@ -1591,7 +1594,7 @@ public class GenericObjectPool<T> extend
      * extra condition that at least "minIdle" amount of object remain in the
      * pool. When non-positive, no objects will be evicted from the pool due to
      * idle time alone.
-     * 
+     *
      * @see #setSoftMinEvictableIdleTimeMillis
      * @see #getSoftMinEvictableIdleTimeMillis
      */
@@ -1646,9 +1649,9 @@ public class GenericObjectPool<T> extend
      */
     private EvictionPolicy<T> evictionPolicy = new DefaultEvictionPolicy<T>();
 
-    /** Object used to ensure thread safety of eviction process */ 
+    /** Object used to ensure thread safety of eviction process */
     private final Object evictionLock = new Object();
-    
+
     /** Object used to ensure closed() is only called once. */
     private final Object closeLock = new Object();
 

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java?rev=1324914&r1=1324913&r2=1324914&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java Wed Apr 11 18:50:49 2012
@@ -195,7 +195,7 @@ public class TestGenericKeyedObjectPool 
             assertEquals(99 - i,pool.getNumActive(""));
             assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
         }
-        
+
         for(int i=0;i<100;i++) {
             active[i] = pool.borrowObject("a");
         }
@@ -206,13 +206,13 @@ public class TestGenericKeyedObjectPool 
             assertEquals(99 - i,pool.getNumActive("a"));
             assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle("a"));
         }
-        
+
         // total number of idle instances is twice maxIdle
         assertEquals(16, pool.getNumIdle());
         // Each pool is at the sup
         assertEquals(8, pool.getNumIdle(""));
         assertEquals(8, pool.getNumIdle("a"));
-             
+
     }
 
     @Test(timeout=60000)
@@ -273,11 +273,11 @@ public class TestGenericKeyedObjectPool 
         assertNotNull(o4);
         assertEquals(0, pool.getNumIdle());
         assertEquals(0, pool.getNumIdle("b"));
-        
+
         pool.setMaxTotal(4);
         Object o5 = pool.borrowObject("b");
         assertNotNull(o5);
-        
+
         assertEquals(2, pool.getNumActive("a"));
         assertEquals(2, pool.getNumActive("b"));
         assertEquals(pool.getMaxTotal(),
@@ -519,7 +519,7 @@ public class TestGenericKeyedObjectPool 
                 }
             }
             if(testThread.failed()) {
-                fail("Thread failed: " + threads.indexOf(testThread) + "\n" + 
+                fail("Thread failed: " + threads.indexOf(testThread) + "\n" +
                         getExceptionTrace(testThread._exception));
             }
         }
@@ -532,11 +532,11 @@ public class TestGenericKeyedObjectPool 
         pool.setMaxWait(1000L);
         runTestThreads(20, 100, 50, pool);
     }
-    
+
     /**
      * Verifies that maxTotal is not exceeded when factory destroyObject
      * has high latency, testOnReturn is set and there is high incidence of
-     * validation failures. 
+     * validation failures.
      */
     @Test(timeout=60000)
     public void testMaxTotalInvariant() throws Exception {
@@ -607,7 +607,7 @@ public class TestGenericKeyedObjectPool 
         String key = "A";
 
         pool.preparePool(key);
-        assertTrue("Should be 5 idle, found " + 
+        assertTrue("Should be 5 idle, found " +
                 pool.getNumIdle(),pool.getNumIdle() == 5);
 
         try { Thread.sleep(150L); } catch(InterruptedException e) { }
@@ -704,19 +704,19 @@ public class TestGenericKeyedObjectPool 
         assertEquals("returned", s, pool.borrowObject(key));
         assertEquals("new-4", "key4", pool.borrowObject(key));
     }
-    
+
     /**
      * Test to make sure evictor visits least recently used objects first,
-     * regardless of FIFO/LIFO 
-     * 
+     * regardless of FIFO/LIFO
+     *
      * JIRA: POOL-86
-     */ 
+     */
     @Test(timeout=60000)
     public void testEvictionOrder() throws Exception {
         checkEvictionOrder(false);
         checkEvictionOrder(true);
     }
-    
+
     private void checkEvictionOrder(boolean lifo) throws Exception {
         SimpleFactory<Integer> factory = new SimpleFactory<Integer>();
         GenericKeyedObjectPool<Integer,String> pool =
@@ -724,25 +724,25 @@ public class TestGenericKeyedObjectPool 
         pool.setNumTestsPerEvictionRun(2);
         pool.setMinEvictableIdleTimeMillis(100);
         pool.setLifo(lifo);
-        
+
         for (int i = 0; i < 3; i ++) {
             Integer key = new Integer(i);
             for (int j = 0; j < 5; j++) {
                 pool.addObject(key);
             }
         }
-        
+
         // Make all evictable
         Thread.sleep(200);
-        
-        /* 
+
+        /*
          * Initial state (Key, Object) pairs in order of age:
-         * 
+         *
          * (0,0), (0,1), (0,2), (0,3), (0,4)
          * (1,5), (1,6), (1,7), (1,8), (1,9)
          * (2,10), (2,11), (2,12), (2,13), (2,14)
          */
-        
+
         pool.evict(); // Kill (0,0),(0,1)
         assertEquals(3, pool.getNumIdle(zero));
         String objZeroA = pool.borrowObject(zero);
@@ -751,7 +751,7 @@ public class TestGenericKeyedObjectPool 
         String objZeroB = pool.borrowObject(zero);
         assertTrue(objZeroB.equals("03"));
         assertEquals(1, pool.getNumIdle(zero));
-        
+
         pool.evict(); // Kill remaining 0 survivor and (1,5)
         assertEquals(0, pool.getNumIdle(zero));
         assertEquals(4, pool.getNumIdle(one));
@@ -761,7 +761,7 @@ public class TestGenericKeyedObjectPool 
         String objOneB = pool.borrowObject(one);
         assertTrue(lifo ? objOneB.equals("18") : objOneB.equals("17"));
         assertEquals(2, pool.getNumIdle(one));
-        
+
         pool.evict(); // Kill remaining 1 survivors
         assertEquals(0, pool.getNumIdle(one));
         pool.evict(); // Kill (2,10), (2,11)
@@ -770,8 +770,8 @@ public class TestGenericKeyedObjectPool 
         assertTrue(lifo ? objTwoA.equals("214") : objTwoA.equals("212"));
         assertEquals(2, pool.getNumIdle(two));
         pool.evict(); // All dead now
-        assertEquals(0, pool.getNumIdle(two));  
-        
+        assertEquals(0, pool.getNumIdle(two));
+
         pool.evict(); // Should do nothing - make sure no exception
         // Currently 2 zero, 2 one and 1 two active. Return them
         pool.returnObject(zero, objZeroA);
@@ -781,7 +781,7 @@ public class TestGenericKeyedObjectPool 
         pool.returnObject(two, objTwoA);
         // Remove all idle objects
         pool.clear();
-        
+
         // Reload
         pool.setMinEvictableIdleTimeMillis(500);
         factory.counter = 0; // Reset counter
@@ -792,8 +792,8 @@ public class TestGenericKeyedObjectPool 
             }
             Thread.sleep(200);
         }
-        
-        // 0's are evictable, others not 
+
+        // 0's are evictable, others not
         pool.evict(); // Kill (0,0),(0,1)
         assertEquals(3, pool.getNumIdle(zero));
         pool.evict(); // Kill (0,2),(0,3)
@@ -828,18 +828,18 @@ public class TestGenericKeyedObjectPool 
             assertEquals("15", obj);
         }
     }
-    
-    
+
+
     /**
      * Verifies that the evictor visits objects in expected order
-     * and frequency. 
+     * and frequency.
      */
     @Test(timeout=60000)
     public void testEvictorVisiting() throws Exception {
         checkEvictorVisiting(true);
-        checkEvictorVisiting(false);  
+        checkEvictorVisiting(false);
     }
-    
+
     private void checkEvictorVisiting(boolean lifo) throws Exception {
         VisitTrackerFactory<Integer> factory = new VisitTrackerFactory<Integer>();
         GenericKeyedObjectPool<Integer,VisitTracker<Integer>> pool =
@@ -862,35 +862,35 @@ public class TestGenericKeyedObjectPool 
         pool.returnObject(zero, obj);
         obj = pool.borrowObject(zero);
         pool.returnObject(zero, obj);
-        //  borrow, return, borrow, return 
+        //  borrow, return, borrow, return
         //  FIFO will move 0 and 1 to end - 2,3,4,5,6,7,0,1
         //  LIFO, 7 out, then in, then out, then in - 7,6,5,4,3,2,1,0
         pool.evict();  // Should visit 02 and 03 in either case
         for (int i = 0; i < 8; i++) {
-            VisitTracker<Integer> tracker = pool.borrowObject(zero);    
+            VisitTracker<Integer> tracker = pool.borrowObject(zero);
             if (tracker.getId() >= 4) {
                 assertEquals("Unexpected instance visited " + tracker.getId(),
                         0, tracker.getValidateCount());
             } else {
-                assertEquals("Instance " +  tracker.getId() + 
+                assertEquals("Instance " +  tracker.getId() +
                         " visited wrong number of times.",
                         1, tracker.getValidateCount());
             }
-        } 
+        }
         // 0's are all out
-        
+
         pool.setNumTestsPerEvictionRun(3);
-        
+
         pool.evict(); // 10, 11, 12
         pool.evict(); // 13, 14, 15
-        
+
         obj = pool.borrowObject(one);
         pool.returnObject(one, obj);
         obj = pool.borrowObject(one);
         pool.returnObject(one, obj);
         obj = pool.borrowObject(one);
         pool.returnObject(one, obj);
-        // borrow, return, borrow, return 
+        // borrow, return, borrow, return
         //  FIFO 3,4,5,^,6,7,0,1,2
         //  LIFO 7,6,^,5,4,3,2,1,0
         // In either case, pointer should be at 6
@@ -907,18 +907,18 @@ public class TestGenericKeyedObjectPool 
         // LIFO - 27, 10, 11
         // FIFO - 24, 25, 26
         for (int i = 0; i < 8; i++) {
-            VisitTracker<Integer> tracker = pool.borrowObject(one);    
-            if ((lifo && tracker.getId() > 1) || 
+            VisitTracker<Integer> tracker = pool.borrowObject(one);
+            if ((lifo && tracker.getId() > 1) ||
                     (!lifo && tracker.getId() > 2)) {
-                assertEquals("Instance " +  tracker.getId() + 
+                assertEquals("Instance " +  tracker.getId() +
                         " visited wrong number of times.",
                         1, tracker.getValidateCount());
             } else {
-                assertEquals("Instance " +  tracker.getId() + 
+                assertEquals("Instance " +  tracker.getId() +
                         " visited wrong number of times.",
                         2, tracker.getValidateCount());
             }
-        } 
+        }
 
         // Randomly generate some pools with random numTests
         // and make sure evictor cycles through elements appropriately
@@ -953,26 +953,26 @@ public class TestGenericKeyedObjectPool 
                 for (int k = 0; k < twoLength; k++) {
                     pool.addObject(two);
                 }
-                
+
                 // Choose a random number of evictor runs
                 int runs = 10 + random.nextInt(50);
                 for (int k = 0; k < runs; k++) {
                     pool.evict();
                 }
-                
+
                 // Total instances in pool
                 int totalInstances = zeroLength + oneLength + twoLength;
-                
+
                 // Number of times evictor should have cycled through pools
                 int cycleCount = (runs * pool.getNumTestsPerEvictionRun())
                     / totalInstances;
-                
+
                 // Look at elements and make sure they are visited cycleCount
                 // or cycleCount + 1 times
                 VisitTracker<Integer> tracker = null;
                 int visitCount = 0;
                 for (int k = 0; k < zeroLength; k++) {
-                    tracker = pool.borrowObject(zero); 
+                    tracker = pool.borrowObject(zero);
                     visitCount = tracker.getValidateCount();
                     if (visitCount < cycleCount || visitCount > cycleCount + 1){
                         fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j,
@@ -981,7 +981,7 @@ public class TestGenericKeyedObjectPool 
                     }
                 }
                 for (int k = 0; k < oneLength; k++) {
-                    tracker = pool.borrowObject(one); 
+                    tracker = pool.borrowObject(one);
                     visitCount = tracker.getValidateCount();
                     if (visitCount < cycleCount || visitCount > cycleCount + 1){
                         fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j,
@@ -991,7 +991,7 @@ public class TestGenericKeyedObjectPool 
                 }
                 int visits[] = new int[twoLength];
                 for (int k = 0; k < twoLength; k++) {
-                    tracker = pool.borrowObject(two); 
+                    tracker = pool.borrowObject(two);
                     visitCount = tracker.getValidateCount();
                     visits[k] = visitCount;
                     if (visitCount < cycleCount || visitCount > cycleCount + 1){
@@ -1010,7 +1010,7 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testConstructors() {
-        
+
         // Make constructor arguments all different from defaults
         int maxTotalPerKey = 1;
         int maxIdle = 2;
@@ -1025,7 +1025,7 @@ public class TestGenericKeyedObjectPool 
         long timeBetweenEvictionRunsMillis = 8;
         boolean blockWhenExhausted = false;
         boolean lifo = false;
-        
+
         GenericKeyedObjectPool<Object,Object> pool =
             new GenericKeyedObjectPool<Object,Object>(null);
         assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY, pool.getMaxTotalPerKey());
@@ -1048,7 +1048,7 @@ public class TestGenericKeyedObjectPool 
         assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED,
                 pool.getBlockWhenExhausted());
         assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_LIFO, pool.getLifo());
-        
+
         GenericKeyedObjectPoolConfig config =
                 new GenericKeyedObjectPoolConfig();
         config.setLifo(lifo);
@@ -1096,7 +1096,7 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringBorrow() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>(); 
+        SimpleFactory<String> factory = new SimpleFactory<String>();
         factory.setThrowExceptionOnDestroy(true);
         factory.setValidationEnabled(true);
         GenericKeyedObjectPool<String,String> pool =
@@ -1118,7 +1118,7 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringReturn() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>(); 
+        SimpleFactory<String> factory = new SimpleFactory<String>();
         factory.setThrowExceptionOnDestroy(true);
         factory.setValidationEnabled(true);
         GenericKeyedObjectPool<String,String> pool =
@@ -1136,7 +1136,7 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnActivateDuringBorrow() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>(); 
+        SimpleFactory<String> factory = new SimpleFactory<String>();
         GenericKeyedObjectPool<String,String> pool =
             new GenericKeyedObjectPool<String,String>(factory);
         String obj1 = pool.borrowObject("one");
@@ -1144,7 +1144,7 @@ public class TestGenericKeyedObjectPool 
         pool.returnObject("one", obj1);
         pool.returnObject("one", obj2);
         factory.setThrowExceptionOnActivate(true);
-        factory.setEvenValid(false);  
+        factory.setEvenValid(false);
         // Activation will now throw every other time
         // First attempt throws, but loop continues and second succeeds
         String obj = pool.borrowObject("one");
@@ -1152,7 +1152,7 @@ public class TestGenericKeyedObjectPool 
         assertEquals(0, pool.getNumIdle("one"));
         assertEquals(1, pool.getNumActive());
         assertEquals(0, pool.getNumIdle());
-        
+
         pool.returnObject("one", obj);
         factory.setValid(false);
         // Validation will now fail on activation when borrowObject returns
@@ -1168,7 +1168,7 @@ public class TestGenericKeyedObjectPool 
         assertEquals(0, pool.getNumActive());
         assertEquals(0, pool.getNumIdle());
     }
-    
+
     @Test(timeout=60000)
     public void testBlockedKeyDoesNotBlockPool() throws Exception {
         SimpleFactory<String> factory = new SimpleFactory<String>();
@@ -1194,7 +1194,7 @@ public class TestGenericKeyedObjectPool 
         // Use 3000ms as the threshold - should avoid timing issues on most
         // (all? platforms)
         assertTrue ("Elapsed time: "+(end-start)+" should be less than 4000",(end-start) < 4000);
-        
+
     }
 
     private static final boolean DISPLAY_THREAD_DETAILS=
@@ -1206,7 +1206,7 @@ public class TestGenericKeyedObjectPool 
     /*
      * Test multi-threaded pool access.
      * Multiple keys, multiple threads, but maxActive only allows half the threads to succeed.
-     * 
+     *
      * This test was prompted by Continuum build failures in the Commons DBCP test case:
      * TestSharedPoolDataSource.testMultipleThreads2()
      * Let's see if the this fails on Continuum too!
@@ -1259,7 +1259,7 @@ public class TestGenericKeyedObjectPool 
                         + " Key: "+(wt._key)
                         + " ObjId: "+wt.objectId
                         );
-            }            
+            }
         }
         assertEquals("Expected half the threads to fail",wtt.length/2,failed);
     }
@@ -1281,7 +1281,7 @@ public class TestGenericKeyedObjectPool 
         pool.setMaxWait(-1);
         runTestThreads(20, 300, 250, pool);
     }
-    
+
     /**
      * Test to make sure that clearOldest does not destroy instances that have been checked out.
      */
@@ -1304,18 +1304,18 @@ public class TestGenericKeyedObjectPool 
             Thread.sleep(20);
         }
         // Now set up a race - one thread wants a new instance, triggering clearOldest
-        // Other goes after an element on death row 
+        // Other goes after an element on death row
         // See if we end up with dead man walking
         SimpleTestThread<Waiter> t2 = new SimpleTestThread<Waiter>(pool, "51");
         Thread thread2 = new Thread(t2);
         thread2.start();  // Triggers clearOldest, killing all of the 0's and the 2 oldest 1's
-        Thread.sleep(50); // Wait for clearOldest to kick off, but not long enough to reach the 1's 
+        Thread.sleep(50); // Wait for clearOldest to kick off, but not long enough to reach the 1's
         Waiter waiter = pool.borrowObject("1");
         Thread.sleep(200); // Wait for execution to happen
         pool.returnObject("1", waiter);  // Will throw IllegalStateException if dead
     }
-    
-    
+
+
     /**
      * Verifies that threads that get parked waiting for keys not in use
      * when the pool is at maxTotal eventually get served.
@@ -1329,7 +1329,7 @@ public class TestGenericKeyedObjectPool 
         pool.setMaxTotal(3);
         pool.setMaxTotalPerKey(3);
         pool.setMaxWait(3000);  // Really a timeout for the test
-        
+
         // Check out and briefly hold 3 "1"s
         WaitingTestThread t1 = new WaitingTestThread(pool, "1", 100);
         WaitingTestThread t2 = new WaitingTestThread(pool, "1", 100);
@@ -1337,12 +1337,12 @@ public class TestGenericKeyedObjectPool 
         t1.start();
         t2.start();
         t3.start();
-        
+
         // Try to get a "2" while all capacity is in use.
         // Thread will park waiting on empty queue. Verify it gets served.
-        pool.borrowObject("2");   
+        pool.borrowObject("2");
     }
-    
+
     /**
      * POOL-192
      * Verify that clear(key) does not leak capacity.
@@ -1371,38 +1371,39 @@ public class TestGenericKeyedObjectPool 
         pool.borrowObject("one");
         pool.close();
     }
-    
+
     /**
      * POOL-189
      */
+    @Test(timeout=60000)
     public void testWhenExhaustedBlockClosePool() throws Exception {
         SimpleFactory<String> factory = new SimpleFactory<String>();
         GenericKeyedObjectPool<String,String> pool =
             new GenericKeyedObjectPool<String,String>(factory);
         pool.setMaxTotalPerKey(1);
         pool.setBlockWhenExhausted(true);
-        pool.setMaxWait(0);
+        pool.setMaxWait(-1);
         String obj1 = pool.borrowObject("a");
-        
+
         // Make sure an object was obtained
         assertNotNull(obj1);
-        
+
         // Create a separate thread to try and borrow another object
         WaitingTestThread wtt = new WaitingTestThread(pool, "a", 200);
         wtt.start();
         // Give wtt time to start
         Thread.sleep(200);
-        
+
         // close the pool (Bug POOL-189)
         pool.close();
-        
+
         // Give interrupt time to take effect
         Thread.sleep(200);
-        
+
         // Check thread was interrupted
-        assertTrue(wtt._thrown instanceof IllegalStateException);
+        assertTrue(wtt._thrown instanceof InterruptedException);
     }
-    
+
     /*
      * Very simple test thread that just tries to borrow an object from
      * the provided pool with the specified key and returns it
@@ -1410,7 +1411,7 @@ public class TestGenericKeyedObjectPool 
     static class SimpleTestThread<T> implements Runnable {
         private final KeyedObjectPool<String,T> _pool;
         private final String _key;
-        
+
         public SimpleTestThread(KeyedObjectPool<String,T> pool, String key) {
             _pool = pool;
             _key = key;
@@ -1426,7 +1427,7 @@ public class TestGenericKeyedObjectPool 
             }
         }
     }
-    
+
     /*
      * Very simple test thread that just tries to borrow an object from
      * the provided pool with the specified key and returns it after a wait
@@ -1436,7 +1437,7 @@ public class TestGenericKeyedObjectPool 
         private final String _key;
         private final long _pause;
         private Throwable _thrown;
-        
+
         private long preborrow; // just before borrow
         private long postborrow; //  borrow returned
         private long postreturn; // after object was returned
@@ -1467,10 +1468,10 @@ public class TestGenericKeyedObjectPool 
             }
         }
     }
-    
+
     static class TestThread<T> implements Runnable {
         private final java.util.Random _random = new java.util.Random();
-        
+
         // Thread config items
         private final KeyedObjectPool<String,T> _pool;
         private final int _iter;
@@ -1571,8 +1572,8 @@ public class TestGenericKeyedObjectPool 
         }
         @Override
         public boolean validateObject(K key, String obj) {
-            if (enableValidation) { 
-                return validateCounter++%2 == 0 ? evenValid : oddValid; 
+            if (enableValidation) {
+                return validateCounter++%2 == 0 ? evenValid : oddValid;
             } else {
                 return valid;
             }
@@ -1591,7 +1592,7 @@ public class TestGenericKeyedObjectPool 
                 throw new Exception();
             }
         }
-        
+
         public void setMaxTotalPerKey(int maxTotalPerKey) {
             this.maxTotalPerKey = maxTotalPerKey;
         }
@@ -1608,22 +1609,22 @@ public class TestGenericKeyedObjectPool 
             evenValid = valid;
             oddValid = valid;
         }
-        
+
         public void setThrowExceptionOnActivate(boolean b) {
             exceptionOnActivate = b;
         }
-        
+
         public void setThrowExceptionOnDestroy(boolean b) {
             exceptionOnDestroy = b;
         }
-        
+
         public void setThrowExceptionOnPassivate(boolean b) {
             exceptionOnPassivate = b;
         }
-        
+
         int counter = 0;
         boolean valid;
-        
+
         int activeCount = 0;
         int validateCounter = 0;
         boolean evenValid = true;
@@ -1634,7 +1635,7 @@ public class TestGenericKeyedObjectPool 
         boolean exceptionOnPassivate = false;
         boolean exceptionOnActivate = false;
         boolean exceptionOnDestroy = false;
-        
+
         private void doWait(long latency) {
             try {
                 Thread.sleep(latency);
@@ -1659,7 +1660,7 @@ public class TestGenericKeyedObjectPool 
         t.printStackTrace(new PrintWriter(sw));
         return sw.toString();
     }
-    
+
     private String formatSettings(String title, String s, int i, String s0, boolean b0, String s1, int i1, String s2, int i2, String s3, int i3,
             String s4, int i4, String s5, int i5, String s6, int i6, int zeroLength, int oneLength, int twoLength){
         StringBuffer sb = new StringBuffer(80);
@@ -1675,7 +1676,7 @@ public class TestGenericKeyedObjectPool 
         sb.append("Lengths=").append(zeroLength).append(',').append(oneLength).append(',').append(twoLength).append(' ');
         return sb.toString();
     }
-    
+
 }
 
 

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java?rev=1324914&r1=1324913&r2=1324914&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java Wed Apr 11 18:50:49 2012
@@ -1177,10 +1177,11 @@ public class TestGenericObjectPool exten
     /**
      * POOL-189
      */
+    @Test(timeout=60000)
     public void testWhenExhaustedBlockClosePool() throws Exception {
         pool.setMaxTotal(1);
         pool.setBlockWhenExhausted(true);
-        pool.setMaxWait(0);
+        pool.setMaxWait(-1);
         Object obj1 = pool.borrowObject();
 
         // Make sure an object was obtained
@@ -1199,7 +1200,7 @@ public class TestGenericObjectPool exten
         Thread.sleep(200);
 
         // Check thread was interrupted
-        assertTrue(wtt._thrown instanceof IllegalStateException);
+        assertTrue(wtt._thrown instanceof InterruptedException);
     }
 
     private class ConcurrentBorrowAndEvictThread extends Thread {