Author: markt
Date: Wed Mar 23 18:53:30 2011
New Revision: 1084672

URL: http://svn.apache.org/viewvc?rev=1084672&view=rev
Log:
Fix POOL-184. Concurrent borrowObject() and evict() can trigger inappropriate 
pool starvation.
Test case based on a patch by Adrian Nistor.

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/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=1084672&r1=1084671&r2=1084672&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 Mar 23 18:53:30 2011
@@ -1529,6 +1529,7 @@ public class GenericKeyedObjectPool<K,V>
                 _totalInternalProcessing--;
             }
         }
+        allocate();
     }
 
     /**

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=1084672&r1=1084671&r2=1084672&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 Mar 23 18:53:30 2011
@@ -1156,6 +1156,7 @@ public class GenericObjectPool<T> extend
                 _numInternalProcessing--;
             }
         }
+        allocate();
     }
 
     /**

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=1084672&r1=1084671&r2=1084672&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 Mar 23 18:53:30 2011
@@ -1280,6 +1280,51 @@ public class TestGenericObjectPool exten
 
     }
     
+    @Test
+    public void testConcurrentBorrowAndEvict() throws Exception {
+
+        pool.setMaxTotal(1);
+        pool.addObject();
+
+        for( int i=0; i<5000; i++) {
+            ConcurrentBorrowAndEvictThread one =
+                    new ConcurrentBorrowAndEvictThread(true);
+            ConcurrentBorrowAndEvictThread two =
+                    new ConcurrentBorrowAndEvictThread(false);
+
+            one.start();
+            two.start();
+            one.join();
+            two.join();
+
+            pool.returnObject(one.obj);
+            
+            if (i % 10 == 0) {
+                System.out.println(i/10);
+            } 
+        }
+    }
+
+    private class ConcurrentBorrowAndEvictThread extends Thread {
+        private boolean borrow;
+        public Object obj;
+        
+        public ConcurrentBorrowAndEvictThread(boolean borrow) {
+            this.borrow = borrow;
+        }
+
+        @Override
+        public void run() {
+            try {
+                if (borrow) {
+                    obj = pool.borrowObject();
+                } else {
+                    pool.evict();
+                }
+            } catch (Exception e) { /* Ignore */}
+        }
+    }
+
     protected GenericObjectPool<Object> pool = null;
 
     private void assertConfiguration(GenericObjectPoolConfig expected, 
GenericObjectPool<Object> actual) throws Exception {


Reply via email to