Author: fhanik
Date: Fri Dec  5 09:36:09 2008
New Revision: 723802

URL: http://svn.apache.org/viewvc?rev=723802&view=rev
Log:
Query collection stats

Added:
    
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
    
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
Modified:
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java

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=723802&r1=723801&r2=723802&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  5 09:36:09 2008
@@ -28,6 +28,7 @@
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
@@ -57,6 +58,9 @@
  */
 
 public class ConnectionPool {
+    public static interface CloseListener {
+        void poolClosed(ConnectionPool pool);
+    }
 
     //logger
     protected static Log log = LogFactory.getLog(ConnectionPool.class);
@@ -64,7 +68,8 @@
     
//===============================================================================
     //         INSTANCE/QUICK ACCESS VARIABLE
     
//===============================================================================
-
+    protected ConcurrentLinkedQueue<CloseListener> listeners = new 
ConcurrentLinkedQueue<CloseListener>();
+    
     /**
      * All the information about the connection pool
      */
@@ -226,11 +231,7 @@
         }
 
         try {
-            //cache the constructor
-            if (proxyClassConstructor == null ) {
-                Class proxyClass = 
Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] 
{java.sql.Connection.class});
-                proxyClassConstructor = proxyClass.getConstructor(new Class[] 
{ InvocationHandler.class });
-            }
+            getProxyConstructor();
             //create the proxy
             //TODO possible optimization, keep track if this connection was 
returned properly, and don't generate a new facade
             Connection connection = 
(Connection)proxyClassConstructor.newInstance(new Object[] { handler });
@@ -243,13 +244,25 @@
         }
 
     }
-    
+
+    public Constructor getProxyConstructor() throws NoSuchMethodException {
+        //cache the constructor
+        if (proxyClassConstructor == null ) {
+            Class proxyClass = 
Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] 
{java.sql.Connection.class});
+            proxyClassConstructor = proxyClass.getConstructor(new Class[] { 
InvocationHandler.class });
+        }
+        return proxyClassConstructor;
+    }
 
     @Override
     protected void finalize() throws Throwable {
         close(true);
     }
 
+    public void addCloseListener(CloseListener listener) {
+        listeners.add(listener);
+    }
+    
     /**
      * Closes the pool and all disconnects all idle connections
      * Active connections will be closed upon the [EMAIL PROTECTED] 
java.sql.Connection#close close} method is called
@@ -288,6 +301,11 @@
         }
         size.set(0);
         if (this.getPoolProperties().isJmxEnabled()) stopJmx();
+        
+        while (listeners.size()>0) {
+            CloseListener listener = listeners.poll();
+            if (listener!=null) listener.poolClosed(this);
+        }
     } //closePool
 
 

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java?rev=723802&r1=723801&r2=723802&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
 Fri Dec  5 09:36:09 2008
@@ -43,6 +43,10 @@
     protected static Log log = LogFactory.getLog(DataSourceProxy.class);
     
     protected volatile ConnectionPool pool = null;
+    public ConnectionPool getPool() {
+        return pool;
+    }
+
     protected PoolProperties poolProperties = new PoolProperties();
 
     public DataSourceProxy() {

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java?rev=723802&r1=723801&r2=723802&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
 Fri Dec  5 09:36:09 2008
@@ -69,8 +69,9 @@
     public abstract void closeInvoked();
 
     protected boolean process(String[] names, Method method, boolean process) {
+        final String name = method.getName();
         for (int i=0; (!process) && i<names.length; i++) {
-            process = compare(names[i],method);
+            process = compare(names[i],name);
         }
         return process;
     }

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=723802&r1=723801&r2=723802&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  5 09:36:09 2008
@@ -16,97 +16,233 @@
  */
 package org.apache.tomcat.jdbc.pool.interceptor;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.LinkedHashMap;
 import java.util.Map.Entry;
 
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.jdbc.pool.ConnectionPool;
 import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
 import org.apache.tomcat.jdbc.pool.PooledConnection;
 
 /**
+ * Slow query report interceptor. Tracks timing of query executions.
  * @author Filip Hanik
  * @version 1.0
  */
-public class SlowQueryReport extends AbstractCreateStatementInterceptor {
-    protected final String[] statements = 
{"createStatement","prepareStatement","prepareCall"};
-    protected final String[] executes = 
{"execute","executeQuery","executeUpdate","executeBatch"};
-
+public class SlowQueryReport extends AbstractCreateStatementInterceptor 
implements ConnectionPool.CloseListener {
+    //logger
+    protected static Log log = LogFactory.getLog(SlowQueryReport.class);
+    /**
+     * the constructors that are used to create statement proxies 
+     */
+    protected static final Constructor[] constructors = new 
Constructor[AbstractCreateStatementInterceptor.statements.length];
+    /**
+     * we will be keeping track of query stats on a per pool basis, do we want 
this, or global?
+     */
     protected static 
IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>> perPoolStats = 
         new IdentityHashMap<ConnectionPool,HashMap<String,QueryStats>>();
-    
+    /**
+     * the queries that are used for this interceptor.
+     */
     protected HashMap<String,QueryStats> queries = null;
-    
+    /**
+     * 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
+    /**
+     * Maximum number of queries we will be storing
+     */
     protected int  maxQueries= 1000; //don't store more than this amount of 
queries
-
     
+    /**
+     * The pool that is associated with this interceptor so that we can clean 
up
+     */
+    private ConnectionPool pool = null;
+
+    /**
+     * Returns the query stats for a given pool
+     * @param pool - the pool we want to retrieve stats for
+     * @return a hash map containing statistics for 0 to maxQueries 
+     */
+    public static HashMap<String,QueryStats> getPoolStats(ConnectionPool pool) 
{
+        return perPoolStats.get(pool);
+    }
     
+    /**
+     * Creates a slow query report interceptor
+     */
     public SlowQueryReport() {
         super();
     }
 
+    /**
+     * returns the query measure threshold.
+     * This value is in milliseconds. If the query is faster than this 
threshold than it wont be accounted for
+     * @return
+     */
     public long getThreshold() {
         return threshold;
     }
 
+    /**
+     * Sets the query measurement threshold. The value is in milliseconds.
+     * If the query goes faster than this threshold it will not be recorded.
+     * @param threshold set to -1 to record every query. Value is in 
milliseconds.
+     */
     public void setThreshold(long threshold) {
         this.threshold = threshold;
     }
 
+    /**
+     * invoked when the connection receives the close request
+     * Not used for now.
+     */
     @Override
     public void closeInvoked() {
         // TODO Auto-generated method stub
         
     }
+    
+    /**
+     * Creates a constructor for a proxy class, if one doesn't already exist
+     * @param idx - the index of the constructor
+     * @param clazz - the interface that the proxy will implement
+     * @return - returns a constructor used to create new instances
+     * @throws NoSuchMethodException
+     */
+    protected Constructor getConstructor(int idx, Class clazz) 
+        throws NoSuchMethodException {
+        if (constructors[idx]==null) {
+            Class proxyClass = 
Proxy.getProxyClass(SlowQueryReport.class.getClassLoader(), new Class[] 
{clazz});
+            constructors[idx] = proxyClass.getConstructor(new Class[] { 
InvocationHandler.class });
+        }
+        return constructors[idx];
+    }
 
+    /**
+     * Creates a statement interceptor to monitor query response times
+     */
     @Override
     public Object createStatement(Object proxy, Method method, Object[] args, 
Object statement) {
-        // TODO Auto-generated method stub
-        String sql = null;
-        if (method.getName().startsWith("prepare")) {
-            sql = (args.length>0 && (args[0] instanceof 
String))?(String)args[0]:null;
+        try {
+            Object result = null;
+            String name = method.getName();
+            String sql = null;
+            Constructor constructor = null;
+            if (compare(statements[0],name)) {
+                //createStatement
+                constructor = getConstructor(0,Statement.class);
+            }else if (compare(statements[1],name)) {
+                //prepareStatement
+                sql = (String)args[0];
+                constructor = getConstructor(1,PreparedStatement.class);
+            }else if (compare(statements[2],name)) {
+                //prepareCall
+                sql = (String)args[0];
+                constructor = getConstructor(2,CallableStatement.class);
+            }else {
+                //do nothing, might be a future unsupported method
+                //so we better bail out and let the system continue
+                return statement;
+            }
+            result = constructor.newInstance(new Object[] { new 
StatementProxy(statement,sql) });
+            return result;
+        }catch (Exception x) {
+            log.warn("Unable to create statement proxy for slow query 
report.",x);
         }
-        return new StatementProxy(statement,sql);
+        return statement;
     }
 
-    protected boolean process(final String[] names, Method method, boolean 
process) {
-        for (int i=0; (!process) && i<names.length; i++) {
-            process = compare(method.getName(),names[i]);
+    /**
+     * [EMAIL PROTECTED]
+     */
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        //see if we already created a map for this pool
+        queries = SlowQueryReport.perPoolStats.get(parent);
+        if (queries==null) {
+            //create the map to hold our stats
+            //however TODO we need to improve the eviction
+            //selection
+            queries = new LinkedHashMap<String,QueryStats>() {
+                @Override
+                protected boolean removeEldestEntry(Entry<String, QueryStats> 
eldest) {
+                    return size()>maxQueries;
+                }
+
+            };
+            perPoolStats.put(parent, queries);
+            //add ourselves to the pool listener, so we can cleanup
+            parent.addCloseListener(this);
         }
-        return process;
+        this.pool = parent;
     }
 
-    protected class QueryStats {
+    
+    public void poolClosed(ConnectionPool pool) {
+        //clean up after ourselves.
+        perPoolStats.remove(pool);
+    }
+    
+
+    
+    /**
+     * 
+     * @author fhanik
+     *
+     */
+    public static class QueryStats {
         private final String query;
         private int nrOfInvocations;
-        private long maxInvocationTime;
+        private long maxInvocationTime = Long.MIN_VALUE;
         private long maxInvocationDate;
-        private long minInvocationTime;
+        private long minInvocationTime = Long.MAX_VALUE;
         private long minInvocationDate;
         private long totalInvocationTime;
         
+        public String toString() {
+            StringBuffer buf = new StringBuffer("QueryStats[query:");
+            buf.append(query);
+            buf.append(", nrOfInvocations:");
+            buf.append(nrOfInvocations);
+            buf.append(", maxInvocationTime:");
+            buf.append(maxInvocationTime);
+            buf.append(", maxInvocationDate:");
+            buf.append(new java.util.Date(maxInvocationDate).toGMTString());
+            buf.append(", minInvocationTime:");
+            buf.append(minInvocationTime);
+            buf.append(", minInvocationDate:");
+            buf.append(new java.util.Date(minInvocationDate).toGMTString());
+            buf.append(", totalInvocationTime:");
+            buf.append(totalInvocationTime);
+            buf.append(", averageInvocationTime:");
+            buf.append((float)totalInvocationTime / (float)nrOfInvocations);
+            buf.append("]");
+            return buf.toString();
+        }
+        
         public QueryStats(String query) {
             this.query = query;
         }
         
-        public void add(long invocationTime) {
-            long now = -1;
+        public void add(long invocationTime, long now) {
             //not thread safe, but don't sacrifice performance for this kind 
of stuff
             maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
             if (maxInvocationTime == invocationTime) {
-                now = System.currentTimeMillis();
                 maxInvocationDate = now;
             }
             minInvocationTime = Math.min(invocationTime, minInvocationTime);
             if (minInvocationTime==invocationTime) {
-                now = (now==-1)?System.currentTimeMillis():now;
                 minInvocationDate = now;
             }
             nrOfInvocations++;
@@ -148,12 +284,17 @@
         public boolean equals(Object other) {
             if (other instanceof QueryStats) {
                 QueryStats qs = (QueryStats)other;
-                return SlowQueryReport.this.compare(qs.query,this.query);
+                return qs.query.equals(this.query);
             } 
             return false;
         }
     }
     
+    /**
+     * Class to measure query execute time
+     * @author fhanik
+     *
+     */
     protected class StatementProxy implements InvocationHandler {
         protected boolean closed = false;
         protected Object delegate;
@@ -164,43 +305,50 @@
         }
         
         public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
+            //get the name of the method for comparison
             final String name = method.getName();
+            //was close invoked?
             boolean close = compare(JdbcInterceptor.CLOSE_VAL,name);
-            if (close && closed) return null; //allow close to be called 
multiple times
+            //allow close to be called multiple times
+            if (close && closed) return null; 
+            //are we calling isClosed?
+            if (compare(JdbcInterceptor.ISCLOSED_VAL,name)) return closed;
+            //if we are calling anything else, bail out
             if (closed) throw new SQLException("Statement closed.");
             boolean process = false;
+            //check to see if we are about to execute a query
             process = process(executes, method, process);
+            //if we are executing, get the current time
             long start = (process)?System.currentTimeMillis():0;
             //execute the query
             Object result =  method.invoke(delegate,args);
-            long delta = (process)?(System.currentTimeMillis()-start):0;
+            //measure the time
+            long delta = 
(process)?(System.currentTimeMillis()-start):Long.MIN_VALUE;
+            //see if we meet the requirements to measure
             if (delta>threshold) {
-                String sql = null;//TODO
-                QueryStats qs = SlowQueryReport.this.queries.get(sql);
-                if (qs == null) {
-                    qs = new QueryStats(sql);
-                    SlowQueryReport.this.queries.put((String)sql,qs);
+                //extract the query string
+                String sql = (query==null && args!=null &&  
args.length>0)?(String)args[0]:query;
+                //if we do batch execution, then we name the query 'batch'
+                if (sql==null && compare(executes[3],name)) {
+                    sql = "batch";
+                }
+                //if we have a query, record the stats
+                if (sql!=null) {
+                    QueryStats qs = SlowQueryReport.this.queries.get(sql);
+                    if (qs == null) {
+                        qs = new QueryStats(sql);
+                        SlowQueryReport.this.queries.put((String)sql,qs);
+                    }
+                    qs.add(delta,start);
                 }
-                qs.add(delta);
-                return qs;
             }
+            //perform close cleanup
             if (close) {
                 closed=true;
                 delegate = null;
+                queries = null;
             }
             return result;
         }
     }
-
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        if (queries==null && SlowQueryReport.perPoolStats.get(parent)==null) {
-            queries = new LinkedHashMap<String,QueryStats>() {
-                @Override
-                protected boolean removeEldestEntry(Entry<String, QueryStats> 
eldest) {
-                    return size()>maxQueries;
-                }
-
-            };
-        }
-    }
 }

Added: 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java?rev=723802&view=auto
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
 (added)
+++ 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
 Fri Dec  5 09:36:09 2008
@@ -0,0 +1,61 @@
+package org.apache.tomcat.jdbc.test;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+import java.util.Random;
+
+
+
+public class CreateTestTable extends DefaultTestCase {
+
+    public CreateTestTable(String name) {
+        super(name);
+    }
+    
+    public void testPopulateData() throws Exception {
+        String insert = "insert into test values (?,?,?,?,?)";
+        this.init();
+        Connection con = datasource.getConnection();
+        Statement st = con.createStatement();
+        try {
+            st.execute("drop table test");
+        }catch (Exception ignore) {}
+        st.execute("create table test(id int not null, val1 varchar(255), val2 
varchar(255), val3 varchar(255), val4 varchar(255))");
+        st.close();
+        PreparedStatement ps = con.prepareStatement(insert);
+        for (int i=0; i<10000000; i++) {
+            ps.setInt(1,i);
+            String s = getRandom();
+            ps.setString(2, s);
+            ps.setString(3, s);
+            ps.setString(4, s);
+            ps.setString(5, s);
+            ps.addBatch();
+            ps.clearParameters();
+            if ((i+1) % 1000 == 0) {
+                System.out.print(".");
+            }
+            if ((i+1) % 10000 == 0) {
+                System.out.print("\n"+(i+1));
+                ps.executeBatch();
+                ps.clearBatch();
+            }
+
+        }
+        ps.close();
+        con.close();
+    }
+    
+    public static Random random = new Random(System.currentTimeMillis());
+    public static String getRandom() {
+        StringBuffer s = new StringBuffer(256);
+        for (int i=0;i<254; i++) {
+            int b = Math.abs(random.nextInt() % 29);
+            char c = (char)(b+65);
+            s.append(c);
+        }
+        return s.toString();
+    }
+
+}

Added: 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java?rev=723802&view=auto
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
 (added)
+++ 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
 Fri Dec  5 09:36:09 2008
@@ -0,0 +1,84 @@
+package org.apache.tomcat.jdbc.test;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.HashMap;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport;
+
+public class TestSlowQueryReport extends DefaultTestCase {
+
+    public TestSlowQueryReport(String name) {
+        super(name);
+    }
+
+    
+    public void testSlowSql() throws Exception {
+        int count = 3;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select count(1) from test where val1 like 'ewqeq' 
and val2 = 'ewrre' and val3 = 'sdada' and val4 = 'dadada'";
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(slowSql);
+            rs.close();
+            st.close();
+        }
+        HashMap<String,SlowQueryReport.QueryStats> map = 
SlowQueryReport.getPoolStats(datasource.getPool());
+        assertNotNull(map);
+        assertEquals(1,map.size());
+        String key = map.keySet().iterator().next();
+        SlowQueryReport.QueryStats stats = map.get(key);
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            PreparedStatement st = con.prepareStatement(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            CallableStatement st = con.prepareCall(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        ConnectionPool pool = datasource.getPool();
+        con.close();
+        tearDown();
+        //make sure we actually did clean up when the pool closed
+        assertNull(SlowQueryReport.getPoolStats(pool));
+    }
+
+    public void testFastSql() throws Exception {
+        int count = 3;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select 1";
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(slowSql);
+            rs.close();
+            st.close();
+        }
+        HashMap<String,SlowQueryReport.QueryStats> map = 
SlowQueryReport.getPoolStats(datasource.getPool());
+        assertNotNull(map);
+        assertEquals(0,map.size());
+        ConnectionPool pool = datasource.getPool();
+        con.close();
+        tearDown();
+        assertNull(SlowQueryReport.getPoolStats(pool));
+    }    
+    
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to