Author: markt
Date: Wed Aug 17 17:03:35 2011
New Revision: 1158831

URL: http://svn.apache.org/viewvc?rev=1158831&view=rev
Log:
POOL-98. Add additional attributes for moniroting (also available via JMX)

Modified:
    commons/proper/pool/trunk/src/changes/changes.xml
    
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java
    
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
    
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java
    
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
    
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/PooledObject.java

Modified: commons/proper/pool/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/changes/changes.xml?rev=1158831&r1=1158830&r2=1158831&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/changes/changes.xml (original)
+++ commons/proper/pool/trunk/src/changes/changes.xml Wed Aug 17 17:03:35 2011
@@ -77,6 +77,9 @@
     <action dev="markt" type="update" issue="POOL-172">
       Expose GOP and GKOP attributes via JMX.
     </action>
+    <action dev="markt" type="update" issue="POOL-98">
+      Add additional attributes (also accessible via JMX) for monitoring.
+    </action>
   </release>
   <release version="1.5.6" date="2011-04-03" description="This is a patch 
release, including bugfixes only.">
     <action dev="markt" type="fix" issue="POOL-179" due-to="Axel Grossmann">

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=1158831&r1=1158830&r2=1158831&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 Aug 17 17:03:35 2011
@@ -19,8 +19,10 @@ package org.apache.commons.pool2.impl;
 
 import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -253,6 +255,8 @@ public class GenericKeyedObjectPool<K,T>
 
         startEvictor(getMinEvictableIdleTimeMillis());
 
+        initStats();
+
         // JMX Registration
         if (config.isJmxEnabled()) {
             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -734,6 +738,7 @@ public class GenericKeyedObjectPool<K,T>
         boolean blockWhenExhausted = this.blockWhenExhausted;
 
         boolean create;
+        long waitTime = 0;
         ObjectDeque<T> objectDeque = register(key);
         
         try {
@@ -751,8 +756,10 @@ public class GenericKeyedObjectPool<K,T>
                         if (borrowMaxWait < 1) {
                             p = objectDeque.getIdleObjects().takeFirst();
                         } else {
+                            waitTime = System.currentTimeMillis();
                             p = objectDeque.getIdleObjects().pollFirst(
                                     borrowMaxWait, TimeUnit.MILLISECONDS);
+                            waitTime = System.currentTimeMillis() - waitTime;
                         }
                     }
                     if (p == null) {
@@ -806,6 +813,7 @@ public class GenericKeyedObjectPool<K,T>
                         if (!validate) {
                             try {
                                 destroy(key, p, true);
+                                
destroyedByBorrowValidationCount.incrementAndGet();
                             } catch (Exception e) {
                                 // Ignore - validation failure is more 
important
                             }
@@ -823,7 +831,21 @@ public class GenericKeyedObjectPool<K,T>
         } finally {
             deregister(key);
         }
-        return p.getObject();
+        
+        borrowedCount.incrementAndGet();
+        synchronized (idleTimes) {
+            idleTimes.add(Long.valueOf(p.getIdleTimeMillis()));
+            idleTimes.poll();
+        }
+        synchronized (waitTimes) {
+            waitTimes.add(Long.valueOf(waitTime));
+            waitTimes.poll();
+        }
+        synchronized (maxBorrowWaitTimeMillisLock) {
+            if (waitTime > maxBorrowWaitTimeMillis) {
+                maxBorrowWaitTimeMillis = waitTime;
+            }
+        }        return p.getObject();
     }
 
 
@@ -857,6 +879,8 @@ public class GenericKeyedObjectPool<K,T>
                      "Returned object not currently part of this pool");
          }
 
+         long activeTime = p.getActiveTimeMillis();
+
          if (getTestOnReturn()) {
              if (!_factory.validateObject(key, t)) {
                  try {
@@ -864,6 +888,7 @@ public class GenericKeyedObjectPool<K,T>
                  } catch (Exception e) {
                      // TODO - Ignore?
                  }
+                 updateStatsReturn(activeTime);
                  return;
              }
          }
@@ -876,6 +901,7 @@ public class GenericKeyedObjectPool<K,T>
              } catch (Exception e) {
                  // TODO - Ignore?
              }
+             updateStatsReturn(activeTime);
              return;
          }
 
@@ -901,9 +927,19 @@ public class GenericKeyedObjectPool<K,T>
                  idleObjects.addLast(p);
              }
          }
+         updateStatsReturn(activeTime);
      }
 
 
+     private void updateStatsReturn(long activeTime) {
+         returnedCount.incrementAndGet();
+         synchronized (activeTimes) {
+             activeTimes.add(Long.valueOf(activeTime));
+             activeTimes.poll();
+         }
+     }
+
+     
      /**
       * {@inheritDoc}
       * <p>Activation of this method decrements the active count associated 
with
@@ -1195,6 +1231,7 @@ public class GenericKeyedObjectPool<K,T>
 
             if (idleEvictTime < underTest.getIdleTimeMillis()) {
                 destroy(evictionKey, underTest, true);
+                destroyedByEvictorCount.incrementAndGet();
             } else {
                 if (testWhileIdle) {
                     boolean active = false;
@@ -1204,17 +1241,20 @@ public class GenericKeyedObjectPool<K,T>
                         active = true;
                     } catch (Exception e) {
                         destroy(evictionKey, underTest, true);
+                        destroyedByEvictorCount.incrementAndGet();
                     }
                     if (active) {
                         if (!_factory.validateObject(evictionKey,
                                 underTest.getObject())) {
                             destroy(evictionKey, underTest, true);
+                            destroyedByEvictorCount.incrementAndGet();
                         } else {
                             try {
                                 _factory.passivateObject(evictionKey,
                                         underTest.getObject());
                             } catch (Exception e) {
                                 destroy(evictionKey, underTest, true);
+                                destroyedByEvictorCount.incrementAndGet();
                             }
                         }
                     }
@@ -1269,6 +1309,7 @@ public class GenericKeyedObjectPool<K,T>
         }
 
         PooledObject<T> p = new PooledObject<T>(t);
+        createdCount.incrementAndGet();
         objectDeque.getAllObjects().put(t, p);
         return p;
     }
@@ -1289,6 +1330,7 @@ public class GenericKeyedObjectPool<K,T>
                     _factory.destroyObject(key, toDestory.getObject());
                 } finally {
                     objectDeque.getCreateCount().decrementAndGet();
+                    destroyedCount.incrementAndGet();
                     numTotal.decrementAndGet();
                 }
                 return true;
@@ -1556,6 +1598,34 @@ public class GenericKeyedObjectPool<K,T>
 
     
     //--- JMX specific attributes 
----------------------------------------------
+
+    private void initStats() {
+        for (int i = 0; i < AVERAGE_TIMING_STATS_CACHE_SIZE; i++) {
+            activeTimes.add(null);
+            idleTimes.add(null);
+            waitTimes.add(null);
+        }
+    }
+
+    private long getMeanFromStatsCache(Deque<Long> cache) {
+        List<Long> times = new 
ArrayList<Long>(AVERAGE_TIMING_STATS_CACHE_SIZE);
+        synchronized (cache) {
+            times.addAll(cache);
+        }
+        double result = 0;
+        int counter = 0;
+        Iterator<Long> iter = times.iterator();
+        while (iter.hasNext()) {
+            Long time = iter.next();
+            if (time != null) {
+                counter++;
+                result = result * ((counter - 1) / counter) +
+                        time.longValue()/counter;
+            }
+        }
+        return (long) result;
+    }
+
     public Map<String,Integer> getNumActivePerKey() {
         HashMap<String,Integer> result = new HashMap<String,Integer>();
 
@@ -1574,7 +1644,47 @@ public class GenericKeyedObjectPool<K,T>
         }
         return result;
     }
-    
+
+    public long getBorrowedCount() {
+        return borrowedCount.get();
+    }
+
+    public long getReturnedCount() {
+        return returnedCount.get();
+    }
+
+    public long getCreatedCount() {
+        return createdCount.get();
+    }
+
+    public long getDestroyedCount() {
+        return destroyedCount.get();
+    }
+
+    public long getDestroyedByEvictorCount() {
+        return destroyedByEvictorCount.get();
+    }
+
+    public long getDestroyedByBorrowValidationCount() {
+        return destroyedByBorrowValidationCount.get();
+    }
+
+    public long getMeanActiveTimeMillis() {
+        return getMeanFromStatsCache(activeTimes);
+    }
+
+    public long getMeanIdleTimeMillis() {
+        return getMeanFromStatsCache(idleTimes);
+    }
+
+    public long getMeanBorrowWaitTimeMillis() {
+        return getMeanFromStatsCache(waitTimes);
+    }
+
+    public long getMaxBorrowWaitTimeMillis() {
+        return maxBorrowWaitTimeMillis;
+    }
+
     //--- inner classes ----------------------------------------------
 
     /**
@@ -1826,6 +1936,20 @@ public class GenericKeyedObjectPool<K,T>
      */
     private K evictionKey = null;
 
+    // JMX specific attributes
+    private static final int AVERAGE_TIMING_STATS_CACHE_SIZE = 100;
+    private AtomicLong borrowedCount = new AtomicLong(0);
+    private AtomicLong returnedCount = new AtomicLong(0);
+    private AtomicLong createdCount = new AtomicLong(0);
+    private AtomicLong destroyedCount = new AtomicLong(0);
+    private AtomicLong destroyedByEvictorCount = new AtomicLong(0);
+    private AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
+    private final Deque<Long> activeTimes = new LinkedList<Long>();
+    private final Deque<Long> idleTimes = new LinkedList<Long>();
+    private final Deque<Long> waitTimes = new LinkedList<Long>();
+    private Object maxBorrowWaitTimeMillisLock = new Object();
+    private volatile long maxBorrowWaitTimeMillis = 0;
+
     private static final String ONAME_BASE =
         "org.apache.commoms.pool2:type=GenericKeyedObjectPool,name=";
 }

Modified: 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java?rev=1158831&r1=1158830&r2=1158831&view=diff
==============================================================================
--- 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
 (original)
+++ 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
 Wed Aug 17 17:03:35 2011
@@ -38,4 +38,14 @@ public interface GenericKeyedObjectPoolM
     boolean isClosed();
     // JMX specific attributes
     Map<String,Integer> getNumActivePerKey();
+    long getBorrowedCount();
+    long getReturnedCount();
+    long getCreatedCount();
+    long getDestroyedCount();
+    long getDestroyedByEvictorCount();
+    long getDestroyedByBorrowValidationCount();
+    long getMeanActiveTimeMillis();
+    long getMeanIdleTimeMillis();
+    long getMeanBorrowWaitTimeMillis();
+    long getMaxBorrowWaitTimeMillis();
 }

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=1158831&r1=1158830&r2=1158831&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 Aug 17 17:03:35 2011
@@ -18,7 +18,11 @@
 package org.apache.commons.pool2.impl;
 
 import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Deque;
 import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.TimerTask;
@@ -205,6 +209,8 @@ public class GenericObjectPool<T> extend
 
         startEvictor(timeBetweenEvictionRunsMillis);
 
+        initStats();
+
         // JMX Registration
         if (config.isJmxEnabled()) {
             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -722,6 +728,7 @@ public class GenericObjectPool<T> extend
         boolean blockWhenExhausted = this.blockWhenExhausted;
 
         boolean create;
+        long waitTime = 0;
 
         while (p == null) {
             create = false;
@@ -735,8 +742,10 @@ public class GenericObjectPool<T> extend
                     if (borrowMaxWait < 1) {
                         p = idleObjects.takeFirst();
                     } else {
+                        waitTime = System.currentTimeMillis();
                         p = idleObjects.pollFirst(borrowMaxWait,
                                 TimeUnit.MILLISECONDS);
+                        waitTime = System.currentTimeMillis() - waitTime;
                     }
                 }
                 if (p == null) {
@@ -788,6 +797,7 @@ public class GenericObjectPool<T> extend
                     if (!validate) {
                         try {
                             destroy(p);
+                            destroyedByBorrowValidationCount.incrementAndGet();
                         } catch (Exception e) {
                             // Ignore - validation failure is more important
                         }
@@ -803,6 +813,20 @@ public class GenericObjectPool<T> extend
             }
         }
 
+        borrowedCount.incrementAndGet();
+        synchronized (idleTimes) {
+            idleTimes.add(Long.valueOf(p.getIdleTimeMillis()));
+            idleTimes.poll();
+        }
+        synchronized (waitTimes) {
+            waitTimes.add(Long.valueOf(waitTime));
+            waitTimes.poll();
+        }
+        synchronized (maxBorrowWaitTimeMillisLock) {
+            if (waitTime > maxBorrowWaitTimeMillis) {
+                maxBorrowWaitTimeMillis = waitTime;
+            }
+        }
         return p.getObject();
     }
 
@@ -834,6 +858,8 @@ public class GenericObjectPool<T> extend
                     "Returned object not currently part of this pool");
         }
 
+        long activeTime = p.getActiveTimeMillis();
+
         if (getTestOnReturn()) {
             if (!factory.validateObject(obj)) {
                 try {
@@ -841,6 +867,7 @@ public class GenericObjectPool<T> extend
                 } catch (Exception e) {
                     // TODO - Ignore?
                 }
+                updateStatsReturn(activeTime);
                 return;
             }
         }
@@ -853,6 +880,7 @@ public class GenericObjectPool<T> extend
             } catch (Exception e) {
                 // TODO - Ignore?
             }
+            updateStatsReturn(activeTime);
             return;
         }
 
@@ -875,6 +903,15 @@ public class GenericObjectPool<T> extend
                 idleObjects.addLast(p);
             }
         }
+        updateStatsReturn(activeTime);
+    }
+
+    private void updateStatsReturn(long activeTime) {
+        returnedCount.incrementAndGet();
+        synchronized (activeTimes) {
+            activeTimes.add(Long.valueOf(activeTime));
+            activeTimes.poll();
+        }
     }
 
     /**
@@ -1040,6 +1077,7 @@ public class GenericObjectPool<T> extend
                     (idleSoftEvictTime < underTest.getIdleTimeMillis() &&
                             getMinIdle() < idleObjects.size())) {
                 destroy(underTest);
+                destroyedByEvictorCount.incrementAndGet();
             } else {
                 if (testWhileIdle) {
                     boolean active = false;
@@ -1048,15 +1086,18 @@ public class GenericObjectPool<T> extend
                         active = true;
                     } catch (Exception e) {
                         destroy(underTest);
+                        destroyedByEvictorCount.incrementAndGet();
                     }
                     if (active) {
                         if (!factory.validateObject(underTest.getObject())) {
                             destroy(underTest);
+                            destroyedByEvictorCount.incrementAndGet();
                         } else {
                             try {
                                 factory.passivateObject(underTest.getObject());
                             } catch (Exception e) {
                                 destroy(underTest);
+                                destroyedByEvictorCount.incrementAndGet();
                             }
                         }
                     }
@@ -1089,6 +1130,7 @@ public class GenericObjectPool<T> extend
         }
 
         PooledObject<T> p = new PooledObject<T>(t);
+        createdCount.incrementAndGet();
         allObjects.put(t, p);
         return p;
     }
@@ -1099,6 +1141,7 @@ public class GenericObjectPool<T> extend
         try {
             factory.destroyObject(toDestory.getObject());
         } finally {
+            destroyedCount.incrementAndGet();
             createCount.decrementAndGet();
         }
     }
@@ -1212,6 +1255,75 @@ public class GenericObjectPool<T> extend
         }
     }
 
+    //--- JMX specific attributes 
----------------------------------------------
+
+    private void initStats() {
+        for (int i = 0; i < AVERAGE_TIMING_STATS_CACHE_SIZE; i++) {
+            activeTimes.add(null);
+            idleTimes.add(null);
+            waitTimes.add(null);
+        }
+    }
+
+    private long getMeanFromStatsCache(Deque<Long> cache) {
+        List<Long> times = new 
ArrayList<Long>(AVERAGE_TIMING_STATS_CACHE_SIZE);
+        synchronized (cache) {
+            times.addAll(cache);
+        }
+        double result = 0;
+        int counter = 0;
+        Iterator<Long> iter = times.iterator();
+        while (iter.hasNext()) {
+            Long time = iter.next();
+            if (time != null) {
+                counter++;
+                result = result * ((counter - 1) / counter) +
+                        time.longValue()/counter;
+            }
+        }
+        return (long) result;
+    }
+
+    public long getBorrowedCount() {
+        return borrowedCount.get();
+    }
+
+    public long getReturnedCount() {
+        return returnedCount.get();
+    }
+
+    public long getCreatedCount() {
+        return createdCount.get();
+    }
+
+    public long getDestroyedCount() {
+        return destroyedCount.get();
+    }
+
+    public long getDestroyedByEvictorCount() {
+        return destroyedByEvictorCount.get();
+    }
+
+    public long getDestroyedByBorrowValidationCount() {
+        return destroyedByBorrowValidationCount.get();
+    }
+
+    public long getMeanActiveTimeMillis() {
+        return getMeanFromStatsCache(activeTimes);
+    }
+
+    public long getMeanIdleTimeMillis() {
+        return getMeanFromStatsCache(idleTimes);
+    }
+
+    public long getMeanBorrowWaitTimeMillis() {
+        return getMeanFromStatsCache(waitTimes);
+    }
+
+    public long getMaxBorrowWaitTimeMillis() {
+        return maxBorrowWaitTimeMillis;
+    }
+
     // --- inner classes ----------------------------------------------
 
     /**
@@ -1424,6 +1536,20 @@ public class GenericObjectPool<T> extend
     /** An iterator for {@link #idleObjects} that is used by the evictor. */
     private Iterator<PooledObject<T>> evictionIterator = null;
 
+    // JMX specific attributes
+    private static final int AVERAGE_TIMING_STATS_CACHE_SIZE = 100;
+    private AtomicLong borrowedCount = new AtomicLong(0);
+    private AtomicLong returnedCount = new AtomicLong(0);
+    private AtomicLong createdCount = new AtomicLong(0);
+    private AtomicLong destroyedCount = new AtomicLong(0);
+    private AtomicLong destroyedByEvictorCount = new AtomicLong(0);
+    private AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
+    private final Deque<Long> activeTimes = new LinkedList<Long>();
+    private final Deque<Long> idleTimes = new LinkedList<Long>();
+    private final Deque<Long> waitTimes = new LinkedList<Long>();
+    private Object maxBorrowWaitTimeMillisLock = new Object();
+    private volatile long maxBorrowWaitTimeMillis = 0;
+
     private static final String ONAME_BASE =
         "org.apache.commoms.pool2:type=GenericObjectPool,name=";
 }

Modified: 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java?rev=1158831&r1=1158830&r2=1158831&view=diff
==============================================================================
--- 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
 (original)
+++ 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
 Wed Aug 17 17:03:35 2011
@@ -33,4 +33,15 @@ public interface GenericObjectPoolMBean 
     boolean getTestWhileIdle();
     long getTimeBetweenEvictionRunsMillis();
     boolean isClosed();
+    // JMX specific attributes
+    long getBorrowedCount();
+    long getReturnedCount();
+    long getCreatedCount();
+    long getDestroyedCount();
+    long getDestroyedByEvictorCount();
+    long getDestroyedByBorrowValidationCount();
+    long getMeanActiveTimeMillis();
+    long getMeanIdleTimeMillis();
+    long getMeanBorrowWaitTimeMillis();
+    long getMaxBorrowWaitTimeMillis();
 }

Modified: 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/PooledObject.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/PooledObject.java?rev=1158831&r1=1158830&r2=1158831&view=diff
==============================================================================
--- 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/PooledObject.java
 (original)
+++ 
commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/PooledObject.java
 Wed Aug 17 17:03:35 2011
@@ -25,7 +25,8 @@ public class PooledObject<T> implements 
 
     private T object = null;
     private volatile PooledObjectState state = PooledObjectState.IDLE;
-    private long lastActiveTime = System.currentTimeMillis();
+    private long lastBorrowTime = System.currentTimeMillis();
+    private long lastReturnTime = System.currentTimeMillis();
 
     public PooledObject(T object) {
         this.object = object;
@@ -40,19 +41,38 @@ public class PooledObject<T> implements 
     }
 
     /**
-     * Obtain the time in milliseconds since this object was last active.
+     * Obtain the time in milliseconds that this object last spend in the the
+     * active state (it may still be active in which case subsequent calls will
+     * return an increased value).
+     */
+    public long getActiveTimeMillis() {
+        if (lastReturnTime > lastBorrowTime) {
+            return lastReturnTime - lastBorrowTime;
+        } else {
+            return System.currentTimeMillis() - lastBorrowTime;
+        }
+    }
+    
+    /**
+     * Obtain the time in milliseconds that this object last spend in the the
+     * idle state (it may still be idle in which case subsequent calls will
+     * return an increased value).
      */
     public long getIdleTimeMillis() {
-        return System.currentTimeMillis() - lastActiveTime;
+        return System.currentTimeMillis() - lastReturnTime;
     }
     
-    public long getLastActiveTime() {
-        return lastActiveTime;
+    public long getLastBorrowTime() {
+        return lastBorrowTime;
+    }
+
+    public long getLastReturnTime() {
+        return lastReturnTime;
     }
 
     public int compareTo(PooledObject<T> other) {
         final long lastActiveDiff =
-                this.getLastActiveTime() - other.getLastActiveTime();
+                this.getLastReturnTime() - other.getLastReturnTime();
         if (lastActiveDiff == 0) {
             // make sure the natural ordering is consistent with equals
             // see java.lang.Comparable Javadocs
@@ -104,6 +124,7 @@ public class PooledObject<T> implements 
     public synchronized boolean allocate() {
         if (state == PooledObjectState.IDLE) {
             state = PooledObjectState.ALLOCATED;
+            lastBorrowTime = System.currentTimeMillis();
             return true;
         } else if (state == PooledObjectState.MAINTAIN_EVICTION) {
             // TODO Allocate anyway and ignore eviction test
@@ -118,7 +139,7 @@ public class PooledObject<T> implements 
     public synchronized boolean deallocate() {
         if (state == PooledObjectState.ALLOCATED) {
             state = PooledObjectState.IDLE;
-            lastActiveTime = System.currentTimeMillis();
+            lastReturnTime = System.currentTimeMillis();
             return true;
         }
 


Reply via email to