commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sandy...@apache.org
Subject svn commit: r383290 - in /jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH: ./ src/java/org/apache/commons/pool/ src/java/org/apache/commons/pool/impl/ src/test/org/apache/commons/pool/ src/test/org/apache/commons/pool/impl/
Date Sun, 05 Mar 2006 07:00:16 GMT
Author: sandymac
Date: Sat Mar  4 23:00:15 2006
New Revision: 383290

URL: http://svn.apache.org/viewcvs?rev=383290&view=rev
Log:
Back port bug fixes from trunk to 1.3 branch. Fixes include but are not limited to:
* Making GenericObjectPools a FIFO as documented. Issues #33264, #36904.
* Break dependency from GenericObjectKeyedPool to commons-collections. Issue #37431.
* GenericObjectPools now use a shared Timer for eviction instead of many Threads. Issues #33265, #36581.

Modified:
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.properties
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.xml
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/BaseObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/StackObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestKeyedObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
    jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.properties?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.properties (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.properties Sat Mar  4 23:00:15 2006
@@ -21,6 +21,12 @@
 maven.javadoc.author=false
 maven.javadoc.links=http://java.sun.com/j2se/1.4.2/docs/api
 
+# Jar Manifest Additional Attributes
+maven.jar.manifest.attributes.list=Implementation-Vendor-Id,X-Compile-Source-JDK,X-Compile-Target-JDK
+maven.jar.manifest.attribute.Implementation-Vendor-Id=org.apache
+maven.jar.manifest.attribute.X-Compile-Source-JDK=${maven.compile.source}
+maven.jar.manifest.attribute.X-Compile-Target-JDK=${maven.compile.target}
+
 # commons site L&F
 maven.xdoc.jsl=../commons-build/commons-site.jsl
 

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.xml?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.xml (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/project.xml Sat Mar  4 23:00:15 2006
@@ -18,7 +18,8 @@
   <pomVersion>3</pomVersion>
   
   <name>Commons Pool</name>
-  <id>commons-pool</id>
+  <groupId>commons-pool</groupId>
+  <artifactId>commons-pool</artifactId>
   <inceptionYear>2001</inceptionYear>
   <currentVersion>1.3-dev</currentVersion>
   <shortDescription>Commons Object Pooling Library</shortDescription>
@@ -35,11 +36,11 @@
   </organization>
 
   <licenses>
-	<license>
-    	<name>The Apache Software License, Version 2.0</name>
-    	<url>/LICENSE.txt</url>
-    	<distribution>repo</distribution>
-	</license>
+    <license>
+        <name>The Apache Software License, Version 2.0</name>
+        <url>/LICENSE.txt</url>
+        <distribution>repo</distribution>
+    </license>
   </licenses>
   
   <gumpRepositoryId>jakarta</gumpRepositoryId>
@@ -134,42 +135,45 @@
       <email></email>
       <organization>Apache Software Foundation</organization>
     </developer>
+    <developer>
+      <name>Sandy McArthur</name>
+      <id>sandymac</id>
+      <email></email>
+      <organization>Apache Software Foundation</organization>
+    </developer>
   </developers>
   <contributors>
     <contributor>
       <name>Todd Carmichael</name>
       <email>toddc@concur.com</email>
     </contributor>
-    <contributor>
-      <name>Sandy McArthur</name>
-      <email>Sandy AT McArthur DOT org</email>
-    </contributor>
   </contributors>
   
   <dependencies>
-    <dependency>
-      <id>commons-collections</id>
-      <version>2.1</version>
-    </dependency>
 
     <dependency>
-      <id>junit</id>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
       <version>3.8.1</version>
       <properties>
           <comment>Only required to run unit tests</comment>
+          <scope>test</scope>
       </properties>
     </dependency>
 
     <!-- these two are required by maven -->
     <dependency>
-    	<id>xml-apis</id><version>2.0.2</version>
+        <groupId>xml-apis</groupId>
+        <artifactId>xml-apis</artifactId>
+        <version>2.0.2</version>
         <properties>
            <comment>Any JAXP compliant parser (1.2 or later).</comment>
         </properties>
     </dependency>
     <dependency>
-    	<id>xerces</id>
-    	<version>2.0.2</version>
+        <groupId>xerces</groupId>
+        <artifactId>xerces</artifactId>
+        <version>2.0.2</version>
         <properties>
           <comment>Any JAXP compliant parser (1.2 or later).</comment>
         </properties>
@@ -193,6 +197,7 @@
 
     <resources>
       <resource>
+        <directory>${basedir}</directory>
         <targetPath>META-INF</targetPath>
         <includes>
           <include>NOTICE.txt</include>

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/BaseObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/BaseObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/BaseObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/BaseObjectPool.java Sat Mar  4 23:00:15 2006
@@ -79,5 +79,5 @@
         }
     }
     
-    private boolean closed = false;
+    private volatile boolean closed = false;
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java Sat Mar  4 23:00:15 2006
@@ -23,8 +23,10 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.LinkedList;
+import java.util.HashSet;
+import java.util.TimerTask;
 
-import org.apache.commons.collections.CursorableLinkedList;
 import org.apache.commons.pool.BaseKeyedObjectPool;
 import org.apache.commons.pool.KeyedObjectPool;
 import org.apache.commons.pool.KeyedPoolableObjectFactory;
@@ -426,7 +428,6 @@
 
         _poolMap = new HashMap();
         _activeMap = new HashMap();
-        _poolList = new CursorableLinkedList();
 
         startEvictor(_timeBetweenEvictionRunsMillis);
     }
@@ -456,8 +457,8 @@
     }
 
     /**
-     * Returns the cap on the total number of instances from my pool.
-     * @return the cap on the total number of instances from my pool.
+     * Returns the cap on the total number of instances from my pool if non-positive.
+     * @return the cap on the total number of instances from my pool if non-positive.
      * @see #setMaxTotal
      */
     public synchronized int getMaxTotal() {
@@ -465,9 +466,9 @@
     }
 
     /**
-     * Sets the cap on the total number of instances from my pool.
+     * Sets the cap on the total number of instances from my pool if non-positive.
      * @param maxTotal The cap on the total number of instances from my pool.
-     *                  Use a negative value for an infinite number of instances.
+     *                  Use a non-positive value for an infinite number of instances.
      * @see #getMaxTotal
      */
     public synchronized void setMaxTotal(int maxTotal) {
@@ -576,7 +577,7 @@
     public synchronized void setMinIdle(int poolSize) {
         _minIdle = poolSize;
     }
-    
+
     /**
      * Returns the minimum number of idle objects in pool to maintain (per key)
      * @return the minimum number of idle objects in pool to maintain (per key)
@@ -585,7 +586,7 @@
     public synchronized int getMinIdle() {
         return _minIdle;
     }
-    
+
     /**
      * When <tt>true</tt>, objects will be
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
@@ -766,11 +767,10 @@
         long starttime = System.currentTimeMillis();
         boolean newlyCreated = false;
         for(;;) {
-            CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
+            LinkedList pool = (LinkedList)(_poolMap.get(key));
             if(null == pool) {
-                pool = new CursorableLinkedList();
+                pool = new LinkedList();
                 _poolMap.put(key,pool);
-                _poolList.add(key);
             }
             ObjectTimestampPair pair = null;
             // if there are any sleeping, just grab one of those
@@ -788,7 +788,7 @@
                 if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
                     clearOldest();
                 }
-                
+
                 // check if we can create one
                 // (note we know that the num sleeping is 0, else we wouldn't be here)
                 int active = getActiveCount(key);
@@ -811,7 +811,14 @@
                                 if(_maxWait <= 0) {
                                     wait();
                                 } else {
-                                    wait(_maxWait);
+                                    // 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)
+                                    {
+                                        wait(waitTime);
+                                    }
                                 }
                             } catch(InterruptedException e) {
                                 // ignored
@@ -840,9 +847,9 @@
     }
 
     public synchronized void clear() {
-        for(Iterator keyiter = _poolList.iterator(); keyiter.hasNext(); ) {
+        for(Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext(); ) {
             Object key = keyiter.next();
-            CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key));
+            final LinkedList list = (LinkedList)(_poolMap.get(key));
             for(Iterator it = list.iterator(); it.hasNext(); ) {
                 try {
                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
@@ -853,21 +860,23 @@
             }
         }
         _poolMap.clear();
-        _poolList.clear();
+        if (_recentlyEvictedKeys != null) {
+            _recentlyEvictedKeys.clear();
+        }
         _totalIdle = 0;
         notifyAll();
     }
 
     /**
-     * Method clears oldest 15% of objects in pool.  The method sorts the 
+     * Method clears oldest 15% of objects in pool.  The method sorts the
      * objects into a TreeMap and then iterates the first 15% for removal
      */
     public synchronized void clearOldest() {
         // build sorted map of idle objects
         TreeMap map = new TreeMap();
-        for (Iterator keyiter = _poolList.iterator(); keyiter.hasNext();) {
+        for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) {
             Object key = keyiter.next();
-            CursorableLinkedList list = (CursorableLinkedList) _poolMap.get(key);
+            LinkedList list = (LinkedList) _poolMap.get(key);
             for (Iterator 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
@@ -876,11 +885,11 @@
                 map.put(pair, key);
             }
         }
-        
+
         // Now iterate created map and kill the first 15% plus one to account for zero
         Set setPairKeys = map.entrySet();
         int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
-        
+
         Iterator iter = setPairKeys.iterator();
         while (iter.hasNext() && itemsToRemove > 0) {
             Map.Entry entry = (Map.Entry) iter.next();
@@ -889,7 +898,7 @@
             // key references is the key of the list it belongs to.
             Object key = entry.getValue();
             ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey();
-            CursorableLinkedList list = (CursorableLinkedList) _poolMap.get(key);
+            LinkedList list = (LinkedList) _poolMap.get(key);
             list.remove(pairTimeStamp);
 
             try {
@@ -900,20 +909,18 @@
             // if that was the last object for that key, drop that pool
             if (list.isEmpty()) {
                 _poolMap.remove(key);
-                _poolList.remove(key);
             }
             _totalIdle--;
             itemsToRemove--;
         }
         notifyAll();
     }
-     
+
     public synchronized void clear(Object key) {
-        CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key));
+        LinkedList pool = (LinkedList)(_poolMap.remove(key));
         if(null == pool) {
             return;
         } else {
-            _poolList.remove(key);
             for(Iterator it = pool.iterator(); it.hasNext(); ) {
                 try {
                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
@@ -941,7 +948,7 @@
 
     public synchronized int getNumIdle(Object key) {
         try {
-            return((CursorableLinkedList)(_poolMap.get(key))).size();
+            return((LinkedList)(_poolMap.get(key))).size();
         } catch(Exception e) {
             return 0;
         }
@@ -968,12 +975,11 @@
 
         boolean shouldDestroy = false;
         // grab the pool (list) of objects associated with the given key
-        CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get(key));
+        LinkedList pool = (LinkedList) (_poolMap.get(key));
         // if it doesn't exist, create it
         if(null == pool) {
-            pool = new CursorableLinkedList();
+            pool = new LinkedList();
             _poolMap.put(key, pool);
-            _poolList.add(key);
         }
         decrementActiveCount(key);
         // if there's no space in the pool, flag the object for destruction
@@ -981,7 +987,7 @@
         if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
             shouldDestroy = true;
         } else if(success) {
-            pool.addFirst(new ObjectTimestampPair(obj));
+            pool.addLast(new ObjectTimestampPair(obj));
             _totalIdle++;
         }
         notifyAll();
@@ -1012,24 +1018,23 @@
     }
 
     /**
-     * Registers a key for pool control. 
-     * 
+     * Registers a key for pool control.
+     *
      * If <i>populateImmediately</i> is <code>true</code>, the pool will immediately commence
      * a sustain cycle. If <i>populateImmediately</i> is <code>false</code>, the pool will be
      * populated when the next schedules sustain task is run.
-     * 
+     *
      * @param key - The key to register for pool control.
      * @param populateImmediately - If this is <code>true</code>, the pool
      * will start a sustain cycle immediately.
      */
     public synchronized void preparePool(Object key, boolean populateImmediately) {
-        CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
+        LinkedList pool = (LinkedList)(_poolMap.get(key));
         if (null == pool) {
-            pool = new CursorableLinkedList();
+            pool = new LinkedList();
             _poolMap.put(key,pool);
-            _poolList.add(key);
         }
-        
+
         if (populateImmediately) {
             try {
                 // Create the pooled objects
@@ -1040,20 +1045,12 @@
             }
         }
     }
-    
+
     public synchronized void close() throws Exception {
         clear();
-        _poolList = null;
         _poolMap = null;
         _activeMap = null;
-        if(null != _evictionCursor) {
-            _evictionCursor.close();
-            _evictionCursor = null;
-        }
-        if(null != _evictionKeyCursor) {
-            _evictionKeyCursor.close();
-            _evictionKeyCursor = null;
-        }
+        _recentlyEvictedKeys = null;
         if(null != _evictor) {
             _evictor.cancel();
             _evictor = null;
@@ -1071,45 +1068,49 @@
 
     public synchronized void evict() throws Exception {
         Object key = null;
+        if (_recentlyEvictedKeys == null) {
+            _recentlyEvictedKeys = new HashSet(_poolMap.size());
+        }
+        Set remainingKeys = new HashSet(_poolMap.keySet());
+        remainingKeys.removeAll(_recentlyEvictedKeys);
+        Iterator keyIter = remainingKeys.iterator();
+
+        ListIterator objIter = null;
+
         for(int i=0,m=getNumTests();i<m;i++) {
             if(_poolMap.size() > 0) {
-                // if we don't have a key cursor, then create one, and close any object cursor
-                if(null == _evictionKeyCursor) {
-                    _evictionKeyCursor = _poolList.cursor();
-                    key = null;
-                    if(null != _evictionCursor) {
-                        _evictionCursor.close();
-                        _evictionCursor = null;
+                // Find next idle object pool key to work on
+                if (key == null) {
+                    if (!keyIter.hasNext()) {
+                        _recentlyEvictedKeys.clear();
+                        remainingKeys = new HashSet(_poolMap.keySet());
+                        keyIter = remainingKeys.iterator();
+                    }
+                    if (!keyIter.hasNext()) {
+                        // done, there are no keyed pools
+                        return;
                     }
+                    key = keyIter.next();
                 }
-                // if we don't have an object cursor
-                if(null == _evictionCursor) {
-                    // if the _evictionKeyCursor has a next value, then use it
-                    if(_evictionKeyCursor.hasNext()) {
-                        key = _evictionKeyCursor.next();
-                        CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
-                        _evictionCursor = pool.cursor(pool.size());
-                    } else {
-                        // else close the key cursor and loop back around
-                        if(null != _evictionKeyCursor) {
-                            _evictionKeyCursor.close();
-                            _evictionKeyCursor = _poolList.cursor();
-                            if(null != _evictionCursor) {
-                                _evictionCursor.close();
-                                _evictionCursor = null;
-                            }
-                        }
-                        continue;
+
+                // if we don't have a keyed object pool iterator
+                if (objIter == null) {
+                    final LinkedList list = (LinkedList)_poolMap.get(key);
+                    if (_evictLastIndex < 0 || _evictLastIndex > list.size()) {
+                        _evictLastIndex = list.size();
                     }
+                    objIter = list.listIterator(_evictLastIndex);
                 }
+
                 // if the _evictionCursor has a previous object, then test it
-                if(_evictionCursor.hasPrevious()) {
-                    ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
+                if(objIter.hasPrevious()) {
+                    ObjectTimestampPair pair = (ObjectTimestampPair)(objIter.previous());
                     boolean removeObject=false;
                     if(_minEvictableIdleTimeMillis > 0 &&
                        System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
                        removeObject=true;
-                    } else if(_testWhileIdle) {
+                    }
+                    if(_testWhileIdle && removeObject == false) {
                         boolean active = false;
                         try {
                             _factory.activateObject(key,pair.value);
@@ -1131,29 +1132,27 @@
                     }
                     if(removeObject) {
                         try {
-                            _evictionCursor.remove();
+                            objIter.remove();
                             _totalIdle--;
                             _factory.destroyObject(key,pair.value);
 
                             // Do not remove the key from the _poolList or _poolmap, even if the list
-                            // stored in the _poolMap for this key is empty when the 
+                            // stored in the _poolMap for this key is empty when the
                             // {@link #getMinIdle <i>minIdle</i>} is > 0.
-                            // 
+                            //
                             // Otherwise if it was the last object for that key, drop that pool
-                            if ((_minIdle == 0) && (((CursorableLinkedList)(_poolMap.get(key))).isEmpty())) {
+                            if ((_minIdle == 0) && (((LinkedList)(_poolMap.get(key))).isEmpty())) {
                                 _poolMap.remove(key);
-                                _poolList.remove(key);
                             }
                         } catch(Exception e) {
                             ; // ignored
                         }
                     }
                 } else {
-                    // else the _evictionCursor is done, so close it and loop around
-                    if(_evictionCursor != null) {
-                        _evictionCursor.close();
-                        _evictionCursor = null;
-                    }
+                    // else done evicting keyed pool
+                    _recentlyEvictedKeys.add(key);
+                    _evictLastIndex = -1;
+                    objIter = null;
                 }
             }
         }
@@ -1167,8 +1166,8 @@
      * @throws Exception If there was an error whilst creating the pooled objects.
      */
     private synchronized void ensureMinIdle() throws Exception {
-        ListIterator iterator = _poolList.cursor();
-   
+        Iterator iterator = _poolMap.keySet().iterator();
+
         //Check if should sustain the pool
         if (_minIdle > 0) {
             // Loop through all elements in _poolList
@@ -1186,7 +1185,7 @@
     /**
      * Re-creates any needed objects to maintain the minimum levels of
      * pooled objects for the specified key.
-     * 
+     *
      * This method uses {@link #calculateDefecit} to calculate the number
      * of objects to be created. {@link #calculateDefecit} can be overridden to
      * provide a different method of calculating the number of objects to be
@@ -1197,13 +1196,13 @@
     private synchronized void ensureMinIdle(Object key) throws Exception {
         // Calculate current pool objects
         int numberToCreate = calculateDefecit(key);
-        
+
         //Create required pool objects, if none to create, this loop will not be run.
         for (int i = 0; i < numberToCreate; i++) {
             addObject(key);
         }
     }
-    
+
     //--- non-public methods ----------------------------------------
 
     /**
@@ -1217,10 +1216,8 @@
             _evictor = null;
         }
         if(delay > 0) {
-            _evictor = new Evictor(delay);
-            Thread t = new Thread(_evictor);
-            t.setDaemon(true);
-            t.start();
+            _evictor = new Evictor();
+            GenericObjectPool.EVICTION_TIMER.schedule(_evictor, delay, delay);
         }
     }
 
@@ -1228,7 +1225,7 @@
         StringBuffer buf = new StringBuffer();
         buf.append("Active: ").append(getNumActive()).append("\n");
         buf.append("Idle: ").append(getNumIdle()).append("\n");
-        Iterator it = _poolList.iterator();
+        Iterator it = _poolMap.keySet().iterator();
         while(it.hasNext()) {
             buf.append("\t").append(_poolMap.get(it.next())).append("\n");
         }
@@ -1273,23 +1270,23 @@
         }
         return active;
     }
-    
+
     /**
      * This returns the number of objects to create during the pool
-     * sustain cycle. This will ensure that the minimum number of idle 
+     * sustain cycle. This will ensure that the minimum number of idle
      * connections is maintained without going past the maxPool value.
      * <p>
-     * This method has been left public so derived classes can override 
-     * the way the defecit is calculated. ie... Increase/decrease the pool 
+     * This method has been left public so derived classes can override
+     * the way the defecit is calculated. ie... Increase/decrease the pool
      * size at certain times of day to accomodate for usage patterns.
-     *  
+     *
      * @param key - The key of the pool to calculate the number of
      *              objects to be re-created
      * @return The number of objects to be created
      */
     private int calculateDefecit(Object key) {
         int objectDefecit = 0;
-        
+
         //Calculate no of objects needed to be created, in order to have
         //the number of pooled objects < maxActive();
         objectDefecit = getMinIdle() - getNumIdle(key);
@@ -1297,8 +1294,8 @@
             int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
             objectDefecit = Math.min(objectDefecit, growLimit);
         }
-        
-        // Take the maxTotal limit into account 
+
+        // Take the maxTotal limit into account
         if (getMaxTotal() > 0) {
             int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
             objectDefecit = Math.min(objectDefecit, growLimit);
@@ -1311,16 +1308,17 @@
 
     /**
      * A simple "struct" encapsulating an object instance and a timestamp.
-     * 
+     *
      * Implements Comparable, objects are sorted from old to new.
+     *
+     * This is also used by {@link GenericObjectPool}.
      */
-    class ObjectTimestampPair implements Comparable {
+    static class ObjectTimestampPair implements Comparable {
         Object value;
         long tstamp;
 
         ObjectTimestampPair(Object val) {
-            value = val;
-            tstamp = System.currentTimeMillis();
+            this(val, System.currentTimeMillis());
         }
 
         ObjectTimestampPair(Object val, long time) {
@@ -1342,54 +1340,22 @@
     }
 
     /**
-     * The idle object evictor thread.
-     * @see #setTimeBetweenEvictionRunsMillis
+     * The idle object evictor {@link TimerTask}.
+     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
      */
-    class Evictor implements Runnable {
-        private boolean _cancelled = false;
-        private long _delay = 0L;
-
-        public Evictor(long delay) {
-            _delay = delay;
-        }
-
-        void cancel() {
-            _cancelled = true;
-        }
-
+    private class Evictor extends TimerTask {
         public void run() {
-            while(!_cancelled) {
-                long sleeptime = 0L;
-                synchronized(GenericKeyedObjectPool.this) {
-                    sleeptime = _timeBetweenEvictionRunsMillis;
-                }
-                try {
-                    Thread.sleep(sleeptime);
-                } catch(Exception e) {
-                    ; // ignored
-                }
-                //Evict from the pool
-                try {
-                    evict();
-                } catch(Exception e) {
-                    ; // ignored
-                }
-                //Re-create the connections.
-                try {
-                    ensureMinIdle();
-                } catch (Exception e) { 
-                    ; // ignored
-                }
+            //Evict from the pool
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
             }
-            synchronized(GenericKeyedObjectPool.this) {
-                if(null != _evictionCursor) {
-                    _evictionCursor.close();
-                    _evictionCursor = null;
-                }
-                if(null != _evictionKeyCursor) {
-                    _evictionKeyCursor.close();
-                    _evictionKeyCursor = null;
-                }
+            //Re-create the connections.
+            try {
+                ensureMinIdle();
+            } catch (Exception e) {
+                // ignored
             }
         }
     }
@@ -1439,7 +1405,7 @@
     private int _maxActive = DEFAULT_MAX_ACTIVE;
 
     /**
-     * The cap on the total number of instances from the pool.
+     * The cap on the total number of instances from the pool if non-positive.
      * @see #setMaxTotal
      * @see #getMaxTotal
      */
@@ -1557,12 +1523,6 @@
     /** My hash of pools (CursorableLinkedLists). */
     private HashMap _poolMap = null;
 
-    /**
-     * A cursorable list of my pools.
-     * @see GenericKeyedObjectPool.Evictor#run
-     */
-    private CursorableLinkedList _poolList = null;
-
     /** Count of active objects, per key. */
     private HashMap _activeMap = null;
 
@@ -1576,11 +1536,17 @@
     private KeyedPoolableObjectFactory _factory = null;
 
     /**
-     * My idle object eviction thread, if any.
+     * My idle object eviction {@link TimerTask}, if any.
      */
     private Evictor _evictor = null;
 
-    private CursorableLinkedList.Cursor _evictionCursor = null;
-    private CursorableLinkedList.Cursor _evictionKeyCursor = null;
+    /**
+     * Idle object pool keys that have been evicted recently.
+     */
+    private Set _recentlyEvictedKeys = null;
 
+    /**
+     * Position in the _pool where the _evictor last stopped.
+     */
+    private int _evictLastIndex = -1;
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/GenericObjectPool.java Sat Mar  4 23:00:15 2006
@@ -18,11 +18,15 @@
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
 
-import org.apache.commons.collections.CursorableLinkedList;
 import org.apache.commons.pool.BaseObjectPool;
 import org.apache.commons.pool.ObjectPool;
 import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericKeyedObjectPool.ObjectTimestampPair;
 
 /**
  * A configurable {@link ObjectPool} implementation.
@@ -256,6 +260,13 @@
      */
     public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
 
+    //--- package constants -------------------------------------------
+
+    /**
+     * Idle object evition Timer. Shared between all {@link GenericObjectPool}s and {@link GenericKeyedObjectPool} s.
+     */
+    static final Timer EVICTION_TIMER = new Timer(true);
+
     //--- constructors -----------------------------------------------
 
     /**
@@ -417,7 +428,7 @@
         _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
         _testWhileIdle = testWhileIdle;
 
-        _pool = new CursorableLinkedList();
+        _pool = new LinkedList();
         startEvictor(_timeBetweenEvictionRunsMillis);
     }
 
@@ -543,8 +554,8 @@
      * Sets 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)
-     * 
-     * @param minIdle The minimum number of objects. 
+     *
+     * @param minIdle The minimum number of objects.
      * @see #getMinIdle
      */
     public synchronized void setMinIdle(int minIdle) {
@@ -642,7 +653,7 @@
     }
 
     /**
-     * Returns the number of objects to examine during each run of the
+     * Returns the max number of objects to examine during each run of the
      * idle object evictor thread (if any).
      *
      * @see #setNumTestsPerEvictionRun
@@ -653,7 +664,7 @@
     }
 
     /**
-     * Sets the number of objects to examine during each run of the
+     * 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, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
@@ -769,7 +780,6 @@
     public synchronized Object borrowObject() throws Exception {
         assertOpen();
         long starttime = System.currentTimeMillis();
-        boolean newlyCreated = false;
         for(;;) {
             ObjectTimestampPair pair = null;
 
@@ -799,7 +809,14 @@
                                 if(_maxWait <= 0) {
                                     wait();
                                 } else {
-                                    wait(_maxWait);
+                                    // 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)
+                                    {
+                                        wait(waitTime);
+                                    }
                                 }
                             } catch(InterruptedException e) {
                                 // ignored
@@ -817,22 +834,17 @@
             _numActive++;
 
             // create new object when needed
+            boolean newlyCreated = false;
             if(null == pair) {
                 try {
                     Object obj = _factory.makeObject();
                     pair = new ObjectTimestampPair(obj);
                     newlyCreated = true;
-                }
-                catch (Throwable e) {
-                    // object cannot be created
-                    _numActive--;
-                    notifyAll();
-                    if (e instanceof Exception) {
-                        throw (Exception) e;
-                    } else if (e instanceof Error) {
-                        throw (Error) e;
-                    } else {
-                        throw new Exception(e);
+                } finally {
+                    if (!newlyCreated) {
+                        // object cannot be created
+                        _numActive--;
+                        notifyAll();
                     }
                 }
             }
@@ -842,22 +854,22 @@
                 _factory.activateObject(pair.value);
                 if(_testOnBorrow && !_factory.validateObject(pair.value)) {
                     throw new Exception("ValidateObject failed");
-                }                
+                }
                 return pair.value;
-            } 
+            }
             catch (Throwable e) {
                 // object cannot be activated or is invalid
                 _numActive--;
                 notifyAll();
                 try {
                     _factory.destroyObject(pair.value);
-                } 
+                }
                 catch (Throwable e2) {
-                    // cannot destroy broken object 
+                    // cannot destroy broken object
                 }
                 if(newlyCreated) {
                     throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
-                } 
+                }
                 else {
                     continue; // keep looping
                 }
@@ -904,7 +916,7 @@
         assertOpen();
         addObjectToPool(obj, true);
     }
-        
+
     private void addObjectToPool(Object obj, boolean decrementNumActive) throws Exception {
         boolean success = true;
         if(_testOnReturn && !(_factory.validateObject(obj))) {
@@ -925,7 +937,7 @@
         if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) {
             shouldDestroy = true;
         } else if(success) {
-            _pool.addFirst(new ObjectTimestampPair(obj));
+            _pool.addLast(new ObjectTimestampPair(obj));
         }
         notifyAll(); // _numActive has changed
 
@@ -942,10 +954,6 @@
         clear();
         _pool = null;
         _factory = null;
-        if(null != _evictionCursor) {
-            _evictionCursor.close();
-            _evictionCursor = null;
-        }
         startEvictor(-1L);
         super.close();
     }
@@ -963,60 +971,60 @@
     public synchronized void evict() throws Exception {
         assertOpen();
         if(!_pool.isEmpty()) {
-            if(null == _evictionCursor) {
-                _evictionCursor = (_pool.cursor(_pool.size()));
-            } else if(!_evictionCursor.hasPrevious()) {
-                _evictionCursor.close();
-                _evictionCursor = (_pool.cursor(_pool.size()));
+            ListIterator iter;
+            if (evictLastIndex < 0) {
+                iter = _pool.listIterator(_pool.size());
+            } else {
+                iter = _pool.listIterator(evictLastIndex);
             }
             for(int i=0,m=getNumTests();i<m;i++) {
-                if(!_evictionCursor.hasPrevious()) {
-                    _evictionCursor.close();
-                    _evictionCursor = (_pool.cursor(_pool.size()));
-                } else {
-                    boolean removeObject = false;
-                    ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
-                    long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;
-                    if ((_minEvictableIdleTimeMillis > 0) 
+                if(!iter.hasPrevious()) {
+                    iter = _pool.listIterator(_pool.size());
+                }
+                boolean removeObject = false;
+                final ObjectTimestampPair pair = (ObjectTimestampPair)(iter.previous());
+                final long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;
+                if ((_minEvictableIdleTimeMillis > 0)
                         && (idleTimeMilis > _minEvictableIdleTimeMillis)) {
-                        removeObject = true;
-                    } else if ((_softMinEvictableIdleTimeMillis > 0)
+                    removeObject = true;
+                } else if ((_softMinEvictableIdleTimeMillis > 0)
                         && (idleTimeMilis > _softMinEvictableIdleTimeMillis)
                         && (getNumIdle() > getMinIdle())) {
-                        removeObject = true;
-                    } else if(_testWhileIdle) {
-                        boolean active = false;
-                        try {
-                            _factory.activateObject(pair.value);
-                            active = true;
-                        } catch(Exception e) {
+                    removeObject = true;
+                }
+                if(_testWhileIdle && !removeObject) {
+                    boolean active = false;
+                    try {
+                        _factory.activateObject(pair.value);
+                        active = true;
+                    } catch(Exception e) {
+                        removeObject=true;
+                    }
+                    if(active) {
+                        if(!_factory.validateObject(pair.value)) {
                             removeObject=true;
-                        }
-                        if(active) {
-                            if(!_factory.validateObject(pair.value)) {
+                        } else {
+                            try {
+                                _factory.passivateObject(pair.value);
+                            } catch(Exception e) {
                                 removeObject=true;
-                            } else {
-                                try {
-                                    _factory.passivateObject(pair.value);
-                                } catch(Exception e) {
-                                    removeObject=true;
-                                }
                             }
                         }
                     }
-                    if(removeObject) {
-                        try {
-                            _evictionCursor.remove();
-                            _factory.destroyObject(pair.value);
-                        } catch(Exception e) {
-                            ; // ignored
-                        }
+                }
+                if(removeObject) {
+                    try {
+                        iter.remove();
+                        _factory.destroyObject(pair.value);
+                    } catch(Exception e) {
+                        // ignored
                     }
                 }
             }
+            evictLastIndex = iter.previousIndex(); // resume from here
         } // if !empty
     }
-    
+
     /**
      * Check to see if we are below our minimum number of objects
      * if so enough to bring us back to our minimum.
@@ -1040,7 +1048,7 @@
             objectDeficit = Math.min(objectDeficit, growLimit);
         }
         return objectDeficit;
-    } 
+    }
 
     /**
      * Create an object, and place it into the pool.
@@ -1051,7 +1059,7 @@
         Object obj = _factory.makeObject();
         addObjectToPool(obj, false);
     }
-    
+
     //--- non-public methods ----------------------------------------
 
     /**
@@ -1065,10 +1073,8 @@
             _evictor = null;
         }
         if(delay > 0) {
-            _evictor = new Evictor(delay);
-            Thread t = new Thread(_evictor);
-            t.setDaemon(true);
-            t.start();
+            _evictor = new Evictor();
+            EVICTION_TIMER.schedule(_evictor, delay, delay);
         }
     }
 
@@ -1088,7 +1094,7 @@
 
     private int getNumTests() {
         if(_numTestsPerEvictionRun >= 0) {
-            return _numTestsPerEvictionRun;
+            return Math.min(_numTestsPerEvictionRun, _pool.size());
         } else {
             return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun)));
         }
@@ -1097,64 +1103,22 @@
     //--- inner classes ----------------------------------------------
 
     /**
-     * A simple "struct" encapsulating an object instance and a timestamp.
+     * The idle object evictor {@link TimerTask}.
+     * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
      */
-    class ObjectTimestampPair {
-        Object value;
-        long tstamp;
-
-        ObjectTimestampPair(Object val) {
-            this(val,System.currentTimeMillis());
-        }
-
-        ObjectTimestampPair(Object val, long time) {
-            value = val;
-            tstamp = time;
-        }
-    }
-
-    /**
-     * The idle object evictor thread.
-     * @see #setTimeBetweenEvictionRunsMillis
-     */
-    class Evictor implements Runnable {
-        private volatile boolean _cancelled = false;
-        private long _delay = 0L;
-
-        public Evictor(long delay) {
-            _delay = delay;
-        }
-
-        void cancel() {
-            _cancelled = true;
-        }
-
+    private class Evictor extends TimerTask {
         public void run() {
-            while(!_cancelled) {
-                try {
-                    Thread.sleep(_delay);
-                } catch(Exception e) {
-                    // ignored
-                }
-                try {
-                    evict();
-                } catch(Exception e) {
-                    // ignored
-                }
-                try {
-                    ensureMinIdle();
-                } catch(Exception e) {
-                    // ignored
-                }
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
             }
-            synchronized(GenericObjectPool.this) {
-                if(null != _evictionCursor) {
-                    _evictionCursor.close();
-                    _evictionCursor = null;
-                }
+            try {
+                ensureMinIdle();
+            } catch(Exception e) {
+                // ignored
             }
         }
-
     }
 
     /**
@@ -1282,7 +1246,7 @@
     private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
 
     /**
-     * The number of objects to examine during each run of the
+     * 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, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
@@ -1324,7 +1288,7 @@
     private long _softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
 
     /** My pool. */
-    private CursorableLinkedList _pool = null;
+    private LinkedList _pool = null;
 
     /** My {@link PoolableObjectFactory}. */
     private PoolableObjectFactory _factory = null;
@@ -1336,9 +1300,12 @@
     private int _numActive = 0;
 
     /**
-     * My idle object eviction thread, if any.
+     * My idle object eviction {@link TimerTask}, if any.
      */
     private Evictor _evictor = null;
 
-    private CursorableLinkedList.Cursor _evictionCursor = null;
+    /**
+     * Position in the _pool where the _evictor last stopped.
+     */
+    private int evictLastIndex = -1;
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java Sat Mar  4 23:00:15 2006
@@ -70,9 +70,13 @@
                 SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
                 obj = ref.get();
             }
-        }
-        if(null != _factory && null != obj) {
-            _factory.activateObject(obj);
+            if(null != _factory && null != obj) {
+                _factory.activateObject(obj);
+            }
+            if (null != _factory && null != obj && !_factory.validateObject(obj)) {
+                _factory.destroyObject(obj);
+                obj = null;
+            }
         }
         _numActive++;
         return obj;

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/StackObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/StackObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/StackObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/java/org/apache/commons/pool/impl/StackObjectPool.java Sat Mar  4 23:00:15 2006
@@ -122,17 +122,23 @@
     public synchronized Object borrowObject() throws Exception {
         assertOpen();
         Object obj = null;
-        if (!_pool.empty()) {
-            obj = _pool.pop();
-        } else {
-            if(null == _factory) {
-                throw new NoSuchElementException();
+        while (null == obj) {
+            if (!_pool.empty()) {
+                obj = _pool.pop();
             } else {
-                obj = _factory.makeObject();
+                if(null == _factory) {
+                    throw new NoSuchElementException();
+                } else {
+                    obj = _factory.makeObject();
+                }
+            }
+            if(null != _factory && null != obj) {
+                _factory.activateObject(obj);
+            }
+            if (null != _factory && null != obj && !_factory.validateObject(obj)) {
+                _factory.destroyObject(obj);
+                obj = null;
             }
-        }
-        if(null != _factory && null != obj) {
-            _factory.activateObject(obj);
         }
         _numActive++;
         return obj;

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestKeyedObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestKeyedObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestKeyedObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestKeyedObjectPool.java Sat Mar  4 23:00:15 2006
@@ -45,6 +45,18 @@
 
     protected abstract Object makeKey(int n);
 
+    /**
+     * Is the implementations LIFO?
+     * @return
+     */
+    protected abstract boolean isLifo();
+    
+    /**
+     * Is the implementationn FIFO?
+     * @return
+     */
+    protected abstract boolean isFifo();
+
     public void setUp() throws Exception {
     }
     
@@ -90,9 +102,19 @@
         _pool.returnObject(keya,obj0);
         _pool.returnObject(keya,obj2);
         obj2 = _pool.borrowObject(keya);
-        assertEquals(getNthObject(keya,2),obj2);
+        if (isLifo()) {
+            assertEquals(getNthObject(keya,2),obj2);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(keya,0),obj2);
+        }
         obj0 = _pool.borrowObject(keya);
-        assertEquals(getNthObject(keya,0),obj0);
+        if (isLifo()) {
+            assertEquals(getNthObject(keya,0),obj0);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(keya,2),obj0);
+        }
     }
 
     public void testBaseNumActiveNumIdle() throws Exception {

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/TestObjectPool.java Sat Mar  4 23:00:15 2006
@@ -41,6 +41,18 @@
      * object (zero indexed) created by the _pool.
      */
     protected abstract Object getNthObject(int n);
+    
+    /**
+     * Is the implementations LIFO?
+     * @return
+     */
+    protected abstract boolean isLifo();
+    
+    /**
+     * Is the implementationn FIFO?
+     * @return
+     */
+    protected abstract boolean isFifo();
 
     public void setUp() throws Exception {
     }
@@ -105,9 +117,20 @@
         _pool.returnObject(obj0);
         _pool.returnObject(obj2);
         obj2 = _pool.borrowObject();
-        assertEquals(getNthObject(2),obj2);
+        if (isLifo()) {
+            assertEquals(getNthObject(2),obj2);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(0),obj2);
+        }
+            
         obj0 = _pool.borrowObject();
-        assertEquals(getNthObject(0),obj0);
+        if (isLifo()) {
+            assertEquals(getNthObject(0),obj0);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(2),obj0);
+        }
     }
 
     public void testBaseNumActiveNumIdle() throws Exception {

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java Sat Mar  4 23:00:15 2006
@@ -591,6 +591,20 @@
         assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
     }
     
+    public void testFIFO() throws Exception {
+        final Object key = "key";
+        pool.addObject(key); // "key0"
+        pool.addObject(key); // "key1"
+        pool.addObject(key); // "key2"
+        assertEquals("Oldest", "key0", pool.borrowObject(key));
+        assertEquals("Middle", "key1", pool.borrowObject(key));
+        assertEquals("Youngest", "key2", pool.borrowObject(key));
+        assertEquals("new-3", "key3", pool.borrowObject(key));
+        pool.returnObject(key, "r");
+        assertEquals("returned", "r", pool.borrowObject(key));
+        assertEquals("new-4", "key4", pool.borrowObject(key));
+    }
+
     class TestThread implements Runnable {
         java.util.Random _random = new java.util.Random();
         KeyedObjectPool _pool = null;
@@ -670,6 +684,14 @@
         public void passivateObject(Object key, Object obj) { }
         int counter = 0;
         boolean valid;
+    }
+
+    protected boolean isLifo() {
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return true;
     }
 
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java Sat Mar  4 23:00:15 2006
@@ -17,6 +17,9 @@
 package org.apache.commons.pool.impl;
 
 import java.util.NoSuchElementException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -827,7 +830,20 @@
             _complete = true;
         }
     }
-    
+
+    public void testFIFO() throws Exception {
+        pool.addObject(); // "0"
+        pool.addObject(); // "1"
+        pool.addObject(); // "2"
+        assertEquals("Oldest", "0", pool.borrowObject());
+        assertEquals("Middle", "1", pool.borrowObject());
+        assertEquals("Youngest", "2", pool.borrowObject());
+        assertEquals("new-3", "3", pool.borrowObject());
+        pool.returnObject("r");
+        assertEquals("returned", "r", pool.borrowObject());
+        assertEquals("new-4", "4", pool.borrowObject());
+    }
+
     public void testAddObject() throws Exception {
         assertEquals("should be zero idle", 0, pool.getNumIdle());
     	pool.addObject();
@@ -841,6 +857,75 @@
 		assertEquals("should be zero active", 0, pool.getNumActive());
     }
     
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        GenericObjectPool pool = new GenericObjectPool(pof);
+        pool.setTestOnBorrow(true);
+        pool.setTestOnReturn(true);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
     private GenericObjectPool pool = null;
 
     private void assertConfiguration(GenericObjectPool.Config expected, GenericObjectPool actual) throws Exception {
@@ -926,6 +1011,15 @@
         public void setValidationEnabled(boolean b) {
             enableValidation = b;
         }
+    }
+
+    protected boolean isLifo() {
+ 
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return true;
     }
 }
 

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java Sat Mar  4 23:00:15 2006
@@ -23,6 +23,10 @@
 import org.apache.commons.pool.PoolableObjectFactory;
 import org.apache.commons.pool.TestObjectPool;
 
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
 /**
  * @author Rodney Waldhoff
  * @version $Revision$ $Date$
@@ -51,6 +55,81 @@
 
     protected Object getNthObject(int n) {
         return String.valueOf(n);
+    }
+
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        ObjectPool pool = new SoftReferenceObjectPool(pof);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
+    protected boolean isLifo() {
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return false;
     }
 
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java Sat Mar  4 23:00:15 2006
@@ -280,4 +280,12 @@
         public void activateObject(Object key, Object obj) { }
         public void passivateObject(Object key, Object obj) { }
     }
+
+    protected boolean isLifo() {
+        return true;
+    }
+
+    protected boolean isFifo() {
+        return false;
+    }
 }

Modified: jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java?rev=383290&r1=383289&r2=383290&view=diff
==============================================================================
--- jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java (original)
+++ jakarta/commons/proper/pool/branches/1_3_RELEASE_BRANCH/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java Sat Mar  4 23:00:15 2006
@@ -20,6 +20,7 @@
 import java.util.NoSuchElementException;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -142,14 +143,17 @@
         }
     }
 
-    public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
+
+    public void testBorrowWithSometimesInvalidObjects() throws Exception {
         ObjectPool pool = new StackObjectPool(20);
         pool.setFactory(
             new PoolableObjectFactory() {
+                // factory makes Integer objects
                 int counter = 0;
                 public Object makeObject() { return new Integer(counter++); }
                 public void destroyObject(Object obj) { }
                 public boolean validateObject(Object obj) {
+                    // only odd objects are valid
                     if(obj instanceof Integer) {
                         return ((((Integer)obj).intValue() % 2) == 1);
                     } else {
@@ -172,9 +176,67 @@
         Object[] obj = new Object[10];
         for(int i=0;i<10;i++) {
             obj[i] = pool.borrowObject();
+            assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
+            
         }
         for(int i=0;i<10;i++) {
             pool.returnObject(obj[i]);
+            assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
+        }
+        assertEquals(7,pool.getNumIdle());
+    }
+    
+    public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
+        ObjectPool pool = new StackObjectPool(20);
+
+        class TestingPoolableObjectFactory implements PoolableObjectFactory {
+            // factory makes Integer objects
+            int counter = 0;
+            boolean reject = false;
+            public Object makeObject() { return new Integer(counter++); }
+            public void destroyObject(Object obj) { }
+            public boolean validateObject(Object obj) {
+                if (reject) {
+                    // only odd objects are valid
+                    if(obj instanceof Integer) {
+                        return ((((Integer)obj).intValue() % 2) == 1);
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return true;
+                }
+                    
+            }
+            public void activateObject(Object obj) { }
+            public void passivateObject(Object obj) { 
+                if(obj instanceof Integer) {
+                    if((((Integer)obj).intValue() % 3) == 0) {
+                        throw new RuntimeException("Couldn't passivate");
+                    }
+                } else {
+                    throw new RuntimeException("Couldn't passivate");
+                }
+            }
+        };
+        
+        TestingPoolableObjectFactory factory = new TestingPoolableObjectFactory();
+        
+        pool.setFactory(factory);
+
+        Object[] obj = new Object[10];
+        for(int i=0;i<10;i++) {
+            obj[i] = pool.borrowObject();
+            assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
+            
+        }
+        
+        // now reject even numbers
+        factory.reject = true;
+        
+        for(int i=0;i<10;i++) {
+            pool.returnObject(obj[i]);
+            assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
         }
         assertEquals(3,pool.getNumIdle());
     }
@@ -256,6 +318,73 @@
         assertEquals("Destoryed objects should have the stalest object.", i0, d);
     }
 
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        ObjectPool pool = new StackObjectPool(pof, 1);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
     static class SimpleFactory implements PoolableObjectFactory {
         int counter = 0;
         public Object makeObject() { return String.valueOf(counter++); }
@@ -263,6 +392,14 @@
         public boolean validateObject(Object obj) { return true; }
         public void activateObject(Object obj) { }
         public void passivateObject(Object obj) { }
+    }
+
+    protected boolean isLifo() {
+        return true;
+    }
+
+    protected boolean isFifo() {
+        return false;
     }
 }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message