Author: fhanik Date: Wed Dec 10 20:58:11 2008 New Revision: 725575 URL: http://svn.apache.org/viewvc?rev=725575&view=rev Log: Refactor a bit
Modified: 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/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java 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=725575&r1=725574&r2=725575&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 Wed Dec 10 20:58:11 2008 @@ -54,7 +54,7 @@ protected int removeAbandonedTimeout = 60; protected boolean logAbandoned = false; protected int loginTimeout = 10000; - protected String name = "Tomcat Connection Pool["+(poolCounter.addAndGet(1))+","+System.identityHashCode(PoolProperties.class)+"]"; + protected String name = "Tomcat Connection Pool["+(poolCounter.addAndGet(1))+":"+System.identityHashCode(PoolProperties.class)+"]"; protected String password; protected String username; protected long validationInterval = 30000; 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=725575&r1=725574&r2=725575&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 Wed Dec 10 20:58:11 2008 @@ -24,10 +24,8 @@ 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 java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; import javax.management.openmbean.CompositeData; @@ -53,12 +51,12 @@ /** * we will be keeping track of query stats on a per pool basis, do we want this, or global? */ - protected static HashMap<String,HashMap<String,QueryStats>> perPoolStats = - new HashMap<String,HashMap<String,QueryStats>>(); + protected static ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>> perPoolStats = + new ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>>(); /** * the queries that are used for this interceptor. */ - protected HashMap<String,QueryStats> queries = null; + protected ConcurrentHashMap<String,QueryStats> queries = null; /** * The threshold in milliseconds. If the query is faster than this, we don't measure it */ @@ -73,8 +71,8 @@ * @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); + public static ConcurrentHashMap<String,QueryStats> getPoolStats(String poolname) { + return perPoolStats.get(poolname); } /** @@ -171,19 +169,18 @@ */ public void reset(ConnectionPool parent, PooledConnection con) { //see if we already created a map for this pool - queries = SlowQueryReport.perPoolStats.get(parent); + queries = SlowQueryReport.perPoolStats.get(parent.getName()); 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; - } - + queries = new ConcurrentHashMap<String,QueryStats>() { + }; - perPoolStats.put(parent.getName(), queries); + if (perPoolStats.putIfAbsent(parent.getName(), queries)!=null) { + //there already was one + queries = SlowQueryReport.perPoolStats.get(parent.getName()); + } } } @@ -206,6 +203,7 @@ private long minInvocationTime = Long.MAX_VALUE; private long minInvocationDate; private long totalInvocationTime; + private volatile long lastInvocation = 0; public String toString() { StringBuffer buf = new StringBuffer("QueryStats[query:"); @@ -244,6 +242,7 @@ } nrOfInvocations++; totalInvocationTime+=invocationTime; + lastInvocation = now; } public String getQuery() { @@ -285,6 +284,10 @@ } return false; } + + public boolean isOlderThan(QueryStats other) { + return this.lastInvocation < other.lastInvocation; + } } /** @@ -323,7 +326,12 @@ long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE; //see if we meet the requirements to measure if (delta>threshold) { - reportSlowQuery(args, name, start, delta); + try { + //report the slow query + reportSlowQuery(args, name, start, delta); + }catch (Exception t) { + if (log.isWarnEnabled()) log.warn("Unable to process slow query",t); + } } //perform close cleanup if (close) { @@ -342,13 +350,40 @@ } //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); + QueryStats qs = getQueryStats(sql); + if (qs!=null) qs.add(delta,start); + } + } + + private QueryStats getQueryStats(String sql) { + ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries; + if (queries==null) return null; + QueryStats qs = queries.get(sql); + if (qs == null) { + qs = new QueryStats(sql); + if (queries.putIfAbsent(sql,qs)!=null) { + qs = queries.get(sql); + } else { + //we added a new element, see if we need to remove the oldest + if (queries.size() > maxQueries) { + removeOldest(queries); + } } - qs.add(delta,start); } + return qs; + } + + /** + * TODO - implement a better algorithm + * @param queries + */ + protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) { + Iterator<String> it = queries.keySet().iterator(); + while (queries.size()>maxQueries && it.hasNext()) { + String sql = it.next(); + it.remove(); + if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql); + } } } } Modified: 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=725575&r1=725574&r2=725575&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java (original) +++ tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java Wed Dec 10 20:58:11 2008 @@ -5,7 +5,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; -import java.util.HashMap; +import java.util.Map; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport; @@ -30,7 +30,7 @@ rs.close(); st.close(); } - HashMap<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool()); + Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); assertNotNull(map); assertEquals(1,map.size()); String key = map.keySet().iterator().next(); @@ -56,7 +56,7 @@ con.close(); tearDown(); //make sure we actually did clean up when the pool closed - assertNull(SlowQueryReport.getPoolStats(pool)); + assertNull(SlowQueryReport.getPoolStats(pool.getName())); } public void testFastSql() throws Exception { @@ -72,13 +72,13 @@ rs.close(); st.close(); } - HashMap<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool()); + Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName()); assertNotNull(map); assertEquals(0,map.size()); ConnectionPool pool = datasource.getPool(); con.close(); tearDown(); - assertNull(SlowQueryReport.getPoolStats(pool)); + assertNull(SlowQueryReport.getPoolStats(pool.getName())); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]