You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@excalibur.apache.org by le...@apache.org on 2005/11/04 09:14:06 UTC

svn commit: r330744 - in /excalibur/trunk/components/pool/instrumented: project.xml src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java

Author: leif
Date: Fri Nov  4 00:14:01 2005
New Revision: 330744

URL: http://svn.apache.org/viewcvs?rev=330744&view=rev
Log:
Make it possible to trace who checked out outstanding pool elements.

Added:
    excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java
Modified:
    excalibur/trunk/components/pool/instrumented/project.xml
    excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java

Modified: excalibur/trunk/components/pool/instrumented/project.xml
URL: http://svn.apache.org/viewcvs/excalibur/trunk/components/pool/instrumented/project.xml?rev=330744&r1=330743&r2=330744&view=diff
==============================================================================
--- excalibur/trunk/components/pool/instrumented/project.xml (original)
+++ excalibur/trunk/components/pool/instrumented/project.xml Fri Nov  4 00:14:01 2005
@@ -16,7 +16,8 @@
 limitations under the License.
 -->
 <project>
-
+  <currentVersion>2.2-dev</currentVersion>
+  
   <extend>${basedir}/../project-common.xml</extend>
 
   <artifactId>excalibur-pool-instrumented</artifactId>

Added: excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java
URL: http://svn.apache.org/viewcvs/excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java?rev=330744&view=auto
==============================================================================
--- excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java (added)
+++ excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/TraceableResourceLimitingPool.java Fri Nov  4 00:14:01 2005
@@ -0,0 +1,297 @@
+/* 
+ * Copyright 2002-2004 The Apache Software Foundation
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.avalon.excalibur.pool;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A ResourceLimitingPool which can be configured so that it will trace the
+ *  where get is being called fron.  The pool can then be queried for its
+ *  status.
+ *
+ * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
+ * @version CVS $Revision: 1.6 $ $Date: 2004/03/31 08:07:28 $
+ * @since 4.1
+ */
+public class TraceableResourceLimitingPool
+    extends InstrumentedResourceLimitingPool
+{
+    /*---------------------------------------------------------------
+     * Private Fields
+     *-------------------------------------------------------------*/
+    /** True if tracing is enabled for the pool. */
+    private boolean m_tracing;
+    
+    /** Map of elements describing each poolable. */
+    private Map m_elementMap;
+
+    /*---------------------------------------------------------------
+     * Constructors
+     *-------------------------------------------------------------*/
+    /**
+     * Creates a new TraceableResourceLimitingPool
+     *
+     * @param factory The ObjectFactory which will be used to create new Poolables as needed by
+     *  the pool.
+     * @param max Maximum number of Poolables which can be stored in the pool, 0 implies no limit.
+     * @param maxStrict true if the pool should never allow more than max Poolable to be created.
+     *  Will cause an exception to be thrown if more than max Poolables are requested and blocking
+     *  is false.
+     * @param blocking true if the pool should cause a thread calling get() to block when Poolables
+     *  are not currently available on the pool.
+     * @param blockTimeout The maximum amount of time, in milliseconds, that a call to get() will
+     *  block before an exception is thrown.  A value of 0 implies an indefinate wait.
+     * @param trimInterval The minimum interval with which old unused poolables will be removed
+     *  from the pool.  A value of 0 will cause the pool to never trim poolables.
+     * @param trace True if tracing of gets is enabled for the pool.
+     */
+    public TraceableResourceLimitingPool( final ObjectFactory factory,
+                                          int max,
+                                          boolean maxStrict,
+                                          boolean blocking,
+                                          long blockTimeout,
+                                          long trimInterval,
+                                          boolean trace )
+    {
+
+        super( factory, max, maxStrict, blocking, blockTimeout, trimInterval );
+        
+        m_tracing = trace;
+        if ( m_tracing )
+        {
+            m_elementMap = new HashMap();
+        }
+    }
+
+    /*---------------------------------------------------------------
+     * InstrumentedResourceLimitingPool Methods
+     *-------------------------------------------------------------*/
+    /**
+     * Gets a Poolable from the pool.  If there is room in the pool, a new Poolable will be
+     *  created.  Depending on the parameters to the constructor, the method may block or throw
+     *  an exception if a Poolable is not available on the pool.
+     *
+     * @return Always returns a Poolable.  Contract requires that put must always be called with
+     *  the Poolable returned.
+     * @throws Exception An exception may be thrown as described above or if there is an exception
+     *  thrown by the ObjectFactory's newInstance() method.
+     */
+    public Poolable get() throws Exception
+    {
+        if ( m_tracing )
+        {
+            synchronized ( m_semaphore )
+            {
+                Poolable poolable = (Poolable)super.get();
+                
+                PoolElement element = (PoolElement)m_elementMap.get( poolable );
+                if ( element == null )
+                {
+                    element = new PoolElement( poolable );
+                    m_elementMap.put( poolable, element );
+                }
+                element.trace();
+                
+                return poolable;
+            }
+        }
+        else
+        {
+            return super.get();
+        }
+    }
+
+    /**
+     * Returns a poolable to the pool and notifies any thread blocking.
+     *
+     * @param poolable Poolable to return to the pool.
+     */
+    public void put( Poolable poolable )
+    {
+        if ( m_tracing )
+        {
+            synchronized ( m_semaphore )
+            {
+                PoolElement element = (PoolElement)m_elementMap.get( poolable );
+                if ( element == null )
+                {
+                    getLogger().error( "PoolElement not found in put for poolable: " + poolable );
+                }
+                else
+                {
+                    element.clear();
+                }
+                
+                super.put( poolable );
+            }
+        }
+        else
+        {
+            super.put( poolable );
+        }
+    }
+
+    /**
+     * Called when an object is being removed permanently from the pool.
+     * This is the method to override when you need to enforce destructional
+     * policies.
+     * <p>
+     * This method is only called by threads that have m_semaphore locked.
+     *
+     * @param poolable Poolable to be completely removed from the pool.
+     */
+    protected void removePoolable( Poolable poolable )
+    {
+        if ( m_tracing )
+        {
+            PoolElement element = (PoolElement)m_elementMap.remove( poolable );
+            if ( element == null )
+            {
+                getLogger().error(
+                    "PoolElement not found in removePoolable for poolable: " + poolable );
+            }
+        }
+        
+        super.removePoolable( poolable );
+    }
+
+    /*---------------------------------------------------------------
+     * Public Methods
+     *-------------------------------------------------------------*/
+    /**
+     * Returns a snapshot of the current state of the pool.
+     *
+     * @return A snapshot of the current pool state.
+     */
+    public State getState()
+    {
+        if ( m_tracing )
+        {
+            synchronized ( m_semaphore )
+            {
+                // Count how poolables are outstanding.
+                int count = 0;
+                for ( Iterator iter = m_elementMap.values().iterator(); iter.hasNext(); )
+                {
+                    PoolElement element = (PoolElement)iter.next();
+                    if ( element.m_thread != null )
+                    {
+                        count++;
+                    }
+                }
+                
+                // Go back and extract the state.
+                Thread[] threads = new Thread[count];
+                TraceException[] traceExceptions = new TraceException[count];
+                if ( count > 0 )
+                {
+                    int i = 0;
+                    for ( Iterator iter = m_elementMap.values().iterator(); iter.hasNext(); )
+                    {
+                        PoolElement element = (PoolElement)iter.next();
+                        if ( element.m_thread != null )
+                        {
+                            threads[i] = element.m_thread;
+                            traceExceptions[i] = element.m_traceException;
+                            i++;
+                        }
+                    }
+                }
+                
+                return new State( getSize(), getReadySize(), threads, traceExceptions );
+            }
+        }
+        else
+        {
+            throw new IllegalStateException( "Trace is disabled for this pool." );
+        }
+    }
+    
+    /*---------------------------------------------------------------
+     * Inner Classes
+     *-------------------------------------------------------------*/
+    public static class State
+    {
+        private int m_size;
+        private int m_readySize;
+        private Thread[] m_threads;
+        private TraceException[] m_traceExceptions;
+        
+        private State( int size, int readySize, Thread[] threads, TraceException[] traceExceptions )
+        {
+            m_size = size;
+            m_readySize = readySize;
+            m_threads = threads;
+            m_traceExceptions = traceExceptions;
+        }
+        
+        public int getSize()
+        {
+            return m_size;
+        }
+        
+        public int getReadySize()
+        {
+            return m_readySize;
+        }
+        
+        public Thread[] getTraceThreads()
+        {
+            return m_threads;
+        }
+        
+        public TraceException[] getTraceExceptions()
+        {
+            return m_traceExceptions;
+        }
+    }
+    
+    private static class PoolElement
+    {
+        private Poolable m_poolable;
+        private Thread m_thread;
+        private TraceException m_traceException;
+        
+        private PoolElement( Poolable poolable )
+        {
+            m_poolable = poolable;
+        }
+        
+        private void trace()
+        {
+            m_thread = Thread.currentThread();
+            m_traceException = new TraceException();
+            m_traceException.fillInStackTrace();
+        }
+        
+        private void clear()
+        {
+            m_thread = null;
+            m_traceException = null;
+        }
+    }
+    
+    public static class TraceException extends RuntimeException
+    {
+        private TraceException()
+        {
+        }
+    }
+}
+

Modified: excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java
URL: http://svn.apache.org/viewcvs/excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java?rev=330744&r1=330743&r2=330744&view=diff
==============================================================================
--- excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java (original)
+++ excalibur/trunk/components/pool/instrumented/src/java/org/apache/avalon/excalibur/pool/ValidatedResourceLimitingPool.java Fri Nov  4 00:14:01 2005
@@ -25,7 +25,7 @@
  * @since 4.1
  */
 public class ValidatedResourceLimitingPool
-    extends InstrumentedResourceLimitingPool
+    extends TraceableResourceLimitingPool
 {
     /*---------------------------------------------------------------
      * Private Fields
@@ -54,6 +54,34 @@
      *  block before an exception is thrown.  A value of 0 implies an indefinate wait.
      * @param trimInterval The minimum interval with which old unused poolables will be removed
      *  from the pool.  A value of 0 will cause the pool to never trim poolables.
+     * @param trace True if tracing of gets is enabled for the pool.
+     */
+    public ValidatedResourceLimitingPool( final ObjectFactory factory,
+                                          int max,
+                                          boolean maxStrict,
+                                          boolean blocking,
+                                          long blockTimeout,
+                                          long trimInterval,
+                                          boolean trace )
+    {
+        super( factory, max, maxStrict, blocking, blockTimeout, trimInterval, trace );
+    }
+    
+    /**
+     * Creates a new ValidatedResourceLimitingPool
+     *
+     * @param factory The ObjectFactory which will be used to create new Poolables as needed by
+     *  the pool.
+     * @param max Maximum number of Poolables which can be stored in the pool, 0 implies no limit.
+     * @param maxStrict true if the pool should never allow more than max Poolable to be created.
+     *  Will cause an exception to be thrown if more than max Poolables are requested and blocking
+     *  is false.
+     * @param blocking true if the pool should cause a thread calling get() to block when Poolables
+     *  are not currently available on the pool.
+     * @param blockTimeout The maximum amount of time, in milliseconds, that a call to get() will
+     *  block before an exception is thrown.  A value of 0 implies an indefinate wait.
+     * @param trimInterval The minimum interval with which old unused poolables will be removed
+     *  from the pool.  A value of 0 will cause the pool to never trim poolables.
      */
     public ValidatedResourceLimitingPool( final ObjectFactory factory,
                                           int max,
@@ -62,8 +90,7 @@
                                           long blockTimeout,
                                           long trimInterval )
     {
-
-        super( factory, max, maxStrict, blocking, blockTimeout, trimInterval );
+        this( factory, max, maxStrict, blocking, blockTimeout, trimInterval, false );
     }
 
     /*---------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: scm-unsubscribe@excalibur.apache.org
For additional commands, e-mail: scm-help@excalibur.apache.org