You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2008/12/19 18:55:46 UTC

svn commit: r728081 - in /tomcat/trunk/modules/jdbc-pool: ./ doc/ java/org/apache/tomcat/jdbc/pool/ java/org/apache/tomcat/jdbc/pool/interceptor/ test/org/apache/tomcat/jdbc/pool/ test/org/apache/tomcat/jdbc/pool/interceptor/ test/org/apache/tomcat/jdb...

Author: fhanik
Date: Fri Dec 19 09:55:46 2008
New Revision: 728081

URL: http://svn.apache.org/viewvc?rev=728081&view=rev
Log:
Documented interceptors a bit better, implemented setters for interceptor properties

Added:
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java
    tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java
Modified:
    tomcat/trunk/modules/jdbc-pool/build.xml
    tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
    tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
    tomcat/trunk/modules/jdbc-pool/sign.sh

Modified: tomcat/trunk/modules/jdbc-pool/build.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/build.xml?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/build.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/build.xml Fri Dec 19 09:55:46 2008
@@ -23,7 +23,7 @@
   <!-- See "build.properties.sample" in the top level directory for all     -->
   <property name="version.major"         value="1" />
   <property name="version.minor"         value="0" />
-  <property name="version.build"         value="7" />
+  <property name="version.build"         value="8" />
   <property name="version.patch"         value="-beta" />
   <property name="version"               value="${version.major}.${version.minor}.${version.build}${version.patch}" />
   <!-- property values you must customize for successful building!!!        -->

Modified: tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Fri Dec 19 09:55:46 2008
@@ -350,6 +350,75 @@
     of the results from a method invokation as well. You could build query performance analyzer that provides JMX notifications when a 
     query is running longer than the expected time.</p>
   </subsection>
+  <subsection name="JDBC interceptors">
+    <p>Configuring JDBC interceptors is done using the <b>jdbcInterceptors</b> property.
+    The property contains a list of semi colon separated class names. If the classname if not fully qualified it will be prefixed with the 
+    <code>org.apache.tomcat.jdbc.pool.interceptor.</code> prefix.<br/>
+    Example:<br/>
+    <code>
+      jdbcInterceptors=&quot;org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer&quot;
+      <br/>
+      is the same as 
+      <br/>
+      jdbcInterceptors=&quot;ConnectionState;StatementFinalizer&quot;
+    </code><br/>
+    Interceptors can have properties as well. These would be configured within the paranthesis of the class names.
+    Example:<br/>
+    <code>
+      jdbcInterceptors=&quot;ConnectionState;StatementFinalizer(useWeakReferences=true,useEquals=true)&quot;
+    </code><br/>
+    </p>  
+  </subsection>
+  <subsection name="org.apache.tomcat.jdbc.pool.JdbcInterceptor">
+    <p>Abstract base class for all interceptors, can not be instantiated.</p>
+    <attributes>
+      <attribute name="useEquals" required="false">
+        <p>(String as boolean) A custom query to be run when a connection is first created. 
+           The default value is <code>false</code>.
+        </p>
+      </attribute>
+    </attributes>  
+  </subsection>
+  <subsection name="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState">
+    <p>Caches the connection for the following attributes <code>autoCommit</code>, <code>readOnly</code>,
+       <code>transactionIsolation</code> and <code>catalog</code>.
+       It is a performance enhancement to avoid roundtrip to the database when getters are called or setters are called with an already set value.
+    </p>   
+    <attributes>
+    </attributes>  
+  </subsection>
+  <subsection name="org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer">
+    <p>Keeps track of all statements created using <code>createStatement</code>, <code>prepareStatement</code> or <code>prepareCall</code>
+       and closes these statements when the connection is returned to the pool.
+    </p>   
+    <attributes>
+    </attributes>  
+  </subsection>
+  <subsection name="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport">
+    <p>Keeps track of query performance and issues log entries when queries exceed a time threshold of fail.
+       The log level used is <code>WARN</code>
+    </p>   
+    <attributes>
+      <attribute name="threshold" required="false">
+        <p>(int as String) The number of milliseconds a query has to exceed before issuing a log alert.
+           The default value is <code>1000</code> milliseconds.
+        </p>
+      </attribute>
+      <attribute name="maxQueries" required="false">
+        <p>(int as String) The maximum number of queries to keep track of in order to preserve memory space 
+           The default value is <code>1000</code>.
+        </p>
+      </attribute>
+    </attributes>  
+  </subsection>
+  <subsection name="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx">
+    <p>Extends the <code>SlowQueryReport</code> and in addition to log entries it issues JMX notification
+       for monitoring tools to react to. Inherits all the attributes from its parent class.
+       This class uses Tomcat's JMX engine so it wont work outside of the Tomcat container.
+    </p>   
+    <attributes>
+    </attributes>
+  </subsection>
 </section>
 
 <section name="Code Example">
@@ -519,15 +588,41 @@
         </source>
         The <code>compare(String,Method)</code> will use the <code>useEquals</code> flag on an interceptor and do either reference comparison or 
         a string value comparison when the <code>useEquals=true</code> flag is set.
-    </p>                   
+    </p>
+    <p>Pool start/stop<br/>
+       When the connection pool is started or closed, you can be notifed. You will only be notified once per interceptor class
+       even though it is an instance method. and you will be notified using an interceptor currently not attached to a pool.
+       <source>
+       public void poolStarted(ConnectionPool pool) {
+       }
+       
+       public void poolClosed(ConnectionPool pool) {
+       }
+       </source>
+       When overriding these methods, don't forget to call super if you are extending a class other than <code>JdbcInterceptor</code>
+    </p>       
     <p>Configuring interceptors<br/>
        Interceptors are configured using the <code>jdbcInterceptors</code> property or the <code>setJdbcInterceptors</code> method.
        An interceptor can have properties, and would be configured like this
        <source>
-       
        String jdbcInterceptors=&quot;org.apache.tomcat.jdbc.pool.interceptor.ConnectionState(useEquals=true,fast=yes)&quot;
        </source> 
     </p>   
+    <p>Interceptor properties<br/>
+       Since interceptors can have properties, you need to be able to read the values of these properties within your 
+       interceptor. Taking an example like the one above, you can override the <code>setProperties</code> method.
+       <source>
+	   @Override
+	   public void setProperties(Map&lt;String, InterceptorProperty&gt; properties) {
+	       super.setProperties(properties);
+	       final String myprop = &quot;myprop&quot;;
+	       InterceptorProperty p1 = properties.get(myprop);
+	       if (p1!=null) {
+	           setMyprop(Long.parseLong(p1.getValue()));
+	       }
+	   }
+        </source>
+    </p>
   </subsection>
   
   

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java Fri Dec 19 09:55:46 2008
@@ -355,7 +355,7 @@
             try {
                 proxies[i].getInterceptorClass().newInstance().poolStarted(this);
             }catch (Exception x) {
-                log.warn("Unable to inform interceptor of pool start.",x);
+                log.error("Unable to inform interceptor of pool start.",x);
                 if (jmxPool!=null) jmxPool.notify(jmxPool.NOTIFY_INIT, getStackTrace(x));
                 close(true);
                 SQLException ex = new SQLException();
@@ -745,7 +745,7 @@
         return getStackTrace(x);
     }
 
-    protected static String getStackTrace(Exception x) {
+    public static String getStackTrace(Throwable x) {
         if (x == null) {
             return null;
         } else {

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java Fri Dec 19 09:55:46 2008
@@ -20,6 +20,7 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
 
@@ -32,7 +33,7 @@
     public  static final String TOSTRING_VAL = "toString";
     public  static final String ISCLOSED_VAL = "isClosed"; 
     
-    protected List<InterceptorProperty> properties = null; 
+    protected Map<String,InterceptorProperty> properties = null; 
     
     private JdbcInterceptor next = null;
     private boolean useEquals = false;
@@ -75,12 +76,17 @@
      */
     public abstract void reset(ConnectionPool parent, PooledConnection con);
     
-    public List<InterceptorProperty> getProperties() {
+    public Map<String,InterceptorProperty> getProperties() {
         return properties;
     }
 
-    public void setProperties(List<InterceptorProperty> properties) {
+    public void setProperties(Map<String,InterceptorProperty> properties) {
         this.properties = properties;
+        final String useEquals = "useEquals";
+        InterceptorProperty p = properties.get(useEquals);
+        if (p!=null) {
+            setUseEquals(Boolean.parseBoolean(p.getValue()));
+        }
     }
     
     public boolean isUseEquals() {

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java Fri Dec 19 09:55:46 2008
@@ -19,7 +19,9 @@
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -28,6 +30,8 @@
  *
  */
 public class PoolProperties {
+    public static final String PKG_PREFIX = "org.apache.tomcat.jdbc.pool.interceptor.";
+    
     protected static AtomicInteger poolCounter = new AtomicInteger(0);
     protected Properties dbProperties = new Properties();
     protected String url = null;
@@ -430,7 +434,7 @@
     
     public static class InterceptorDefinition {
         protected String className;
-        protected List<InterceptorProperty> properties = new ArrayList<InterceptorProperty>();
+        protected Map<String,InterceptorProperty> properties = new HashMap<String,InterceptorProperty>();
         protected volatile Class clazz = null;
         public InterceptorDefinition(String className) {
             this.className = className;
@@ -445,16 +449,20 @@
         }
         
         public void addProperty(InterceptorProperty p) {
-            properties.add(p);
+            properties.put(p.getName(), p);
         }
         
-        public List<InterceptorProperty> getProperties() {
+        public Map<String,InterceptorProperty> getProperties() {
             return properties;
         }
         
         public Class<? extends JdbcInterceptor> getInterceptorClass() throws ClassNotFoundException {
             if (clazz==null) {
-                clazz = Class.forName(getClassName(), true, this.getClass().getClassLoader());
+                if (getClassName().indexOf(".")<0) {
+                    clazz = Class.forName(PoolProperties.PKG_PREFIX+getClassName(), true, this.getClass().getClassLoader());
+                } else {
+                    clazz = Class.forName(getClassName(), true, this.getClass().getClassLoader());
+                }
             }
             return (Class<? extends JdbcInterceptor>)clazz;
         }
@@ -464,6 +472,7 @@
         String name;
         String value;
         public InterceptorProperty(String name, String value) {
+            assert(name!=null);
             this.name = name;
             this.value = value;
         }
@@ -473,6 +482,17 @@
         public String getValue() {
             return value;
         }
+        public int hashCode() {
+            return name.hashCode();
+        }
+        public boolean equals(Object o) {
+            if (o==this) return true;
+            if (o instanceof InterceptorProperty) {
+                InterceptorProperty other = (InterceptorProperty)o;
+                return other.name.equals(this.name);
+            }
+            return false;
+        }
     }
 
     public boolean isUseEquals() {

Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java Fri Dec 19 09:55:46 2008
@@ -25,6 +25,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import javax.management.openmbean.CompositeDataSupport;
@@ -38,6 +39,7 @@
 import org.apache.tomcat.jdbc.pool.ConnectionPool;
 import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
 import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
 
 /**
  * Slow query report interceptor. Tracks timing of query executions.
@@ -65,7 +67,7 @@
     /**
      * The threshold in milliseconds. If the query is faster than this, we don't measure it
      */
-    protected long threshold = 100; //don't report queries less than this
+    protected long threshold = 1000; //don't report queries less than this
     /**
      * Maximum number of queries we will be storing
      */
@@ -104,6 +106,10 @@
     public void setThreshold(long threshold) {
         this.threshold = threshold;
     }
+    
+    public void setMaxQueries(int maxQueries) {
+        this.maxQueries = maxQueries;
+    }
 
     /**
      * invoked when the connection receives the close request
@@ -214,6 +220,8 @@
         if (sql!=null) {
             QueryStats qs = getQueryStats(sql);
             if (qs!=null) qs.failure(System.currentTimeMillis()-start,start);
+            if (log.isWarnEnabled()) log.warn("Failed query["+sql+"] Stacktrace:"+ConnectionPool.getStackTrace(t));
+
         }
         return sql;
     }
@@ -229,6 +237,7 @@
         if (sql!=null) {
             QueryStats qs = getQueryStats(sql);
             if (qs!=null) qs.add(delta,start);
+            if (log.isWarnEnabled()) log.warn("Slow query["+sql+"] Time to execute:"+delta+" ms.");
         }
         return sql;
     }
@@ -273,6 +282,26 @@
         queries = SlowQueryReport.perPoolStats.get(parent.getName());
     }
 
+    
+
+
+
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        super.setProperties(properties);
+        final String threshold = "threshold";
+        final String maxqueries= "maxQueries";
+        InterceptorProperty p1 = properties.get(threshold);
+        InterceptorProperty p2 = properties.get(maxqueries);
+        if (p1!=null) {
+            setThreshold(Long.parseLong(p1.getValue()));
+        }
+        if (p2!=null) {
+            setMaxQueries(Integer.parseInt(p2.getValue()));
+        }
+    }
+
+
 
 
 

Modified: tomcat/trunk/modules/jdbc-pool/sign.sh
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/sign.sh?rev=728081&r1=728080&r2=728081&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/sign.sh (original)
+++ tomcat/trunk/modules/jdbc-pool/sign.sh Fri Dec 19 09:55:46 2008
@@ -1,4 +1,4 @@
-VERSION=v1.0.7-beta
+VERSION=v1.0.8-beta
 for i in $(find output/release/$VERSION -name "*.zip" -o -name "*.tar.gz"); do
   echo Signing $i
   echo $1|gpg --passphrase-fd 0 -a -b $i

Added: tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java?rev=728081&view=auto
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java (added)
+++ tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java Fri Dec 19 09:55:46 2008
@@ -0,0 +1,43 @@
+package org.apache.tomcat.jdbc.pool.interceptor;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+
+public class TestInterceptor extends JdbcInterceptor {
+    public static boolean poolstarted = false;
+    public static boolean poolclosed = false;
+    public static AtomicInteger instancecount = new AtomicInteger(0);
+
+    @Override
+    public void poolClosed(ConnectionPool pool) {
+        // TODO Auto-generated method stub
+        super.poolClosed(pool);
+        poolclosed = true;
+    }
+
+    @Override
+    public void poolStarted(ConnectionPool pool) {
+        super.poolStarted(pool);
+        poolstarted = true;
+    }
+
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        instancecount.incrementAndGet();
+        super.setProperties(properties);
+    }
+    
+    
+    
+}

Added: tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java?rev=728081&view=auto
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java (added)
+++ tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java Fri Dec 19 09:55:46 2008
@@ -0,0 +1,31 @@
+package org.apache.tomcat.jdbc.test;
+
+import java.sql.Connection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.interceptor.TestInterceptor;
+
+public class TestInterceptorShortName extends DefaultTestCase {
+
+    public TestInterceptorShortName(String name) {
+        super(name);
+    }
+    
+    public void testShortInterceptor() throws Exception {
+        this.datasource = this.createDefaultDataSource();
+        this.datasource.setJdbcInterceptors("TestInterceptor");
+        this.datasource.setMaxActive(1);
+        Connection con = this.datasource.getConnection();
+        assertTrue("Pool should have been started.",TestInterceptor.poolstarted);
+        assertEquals("Only one interceptor should have been called setProperties",1,TestInterceptor.instancecount.get());
+        con.close();
+        this.datasource.close();
+        assertTrue("Pool should have been closed.",TestInterceptor.poolclosed);
+    }
+    
+    
+
+}



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