profiledconnection.java
来自「Jive是基于JSP/JAVA技术构架的一个大型BBS论坛系统,这是Jive论坛」· Java 代码 · 共 897 行 · 第 1/2 页
JAVA
897 行
/** * $RCSfile: ProfiledConnection.java,v $ * $Revision: 1.3 $ * $Date: 2002/04/05 05:39:02 $ * * Copyright (C) 2002 CoolServlets, Inc. All rights reserved. * * This software is the proprietary information of CoolServlets, Inc. * Use is subject to license terms. */package com.jivesoftware.forum.database;import java.sql.*;import java.util.*;import com.jivesoftware.util.*;/** * Wraps a Connection object and collects statistics about the database queries * that are performed.<p> * * Statistics of the profiled Connections can be obtained from the static * methods of this class. Instances of this class are the actual wrappers that * perform profiling. */public class ProfiledConnection extends ConnectionAdapter { /** * Constant for SELECT database queries. */ public static final int SELECT = 0; /** * Constant for UPDATE database queries. */ public static final int UPDATE = 1; /** * Constant for INSERT database queries. */ public static final int INSERT = 2; /** * Constant for DELETE database queries. */ public static final int DELETE = 3; private static long startInsertTime = 0; private static long startUpdateTime = 0; private static long startSelectTime = 0; private static long startDeleteTime = 0; private static long endInsertTime = 0; private static long endUpdateTime = 0; private static long endSelectTime = 0; private static long endDeleteTime = 0; private static long insertCount = 0; private static long updateCount = 0; private static long selectCount = 0; private static long deleteCount = 0; private static long totalInsertTime = 0; private static long totalUpdateTime = 0; private static long totalSelectTime = 0; private static long totalDeleteTime = 0; private static Hashtable insertQueries = new Hashtable(); private static Hashtable updateQueries = new Hashtable(); private static Hashtable selectQueries = new Hashtable(); private static Hashtable deleteQueries = new Hashtable(); /** * Start profiling. */ public static void start() { long now = System.currentTimeMillis(); startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = now; } /** * Stop profiling. */ public static void stop() { endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0; } /** * Returns the total number database queries of a particular type performed. * Valid types are ProfiledConnection.SELECT, ProfiledConnection.UPDATE, * ProfiledConnection.INSERT, and ProfiledConnection.DELETE. * * @param type the type of query to get the count for. * @return the number queries of type <tt>type</tt> performed. */ public static long getQueryCount(int type) { switch (type) { case SELECT: return selectCount; case UPDATE: return updateCount; case INSERT: return insertCount; case DELETE: return deleteCount; default: throw new IllegalArgumentException("Invalid type"); } } /** * * * @param sql the insert sql string. * @param time the length of time the query took in milliseconds */ public static void addQuery(int type, String sql, long time) { // Do nothing if we didn't receive a sql statement if (sql == null || sql.equals("")) { return; } // clean up sql to insert spaces after every ',' sql = reformatQuery(sql); // remove values from query sql = removeQueryValues(sql); ProfiledConnectionEntry entry = null; switch (type) { case SELECT: selectCount++; totalSelectTime += time; entry = (ProfiledConnectionEntry)selectQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); selectQueries.put(sql, entry); } break; case UPDATE: updateCount++; totalUpdateTime += time; entry = (ProfiledConnectionEntry)updateQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); updateQueries.put(sql, entry); } break; case INSERT: insertCount++; totalInsertTime += time; entry = (ProfiledConnectionEntry)insertQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); insertQueries.put(sql, entry); } break; case DELETE: deleteCount++; totalDeleteTime += time; entry = (ProfiledConnectionEntry)deleteQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); deleteQueries.put(sql, entry); } break; default: throw new IllegalArgumentException("Invalid type"); } entry.count++; entry.totalTime += time; } /** * Returns the average number of queries of a certain type that have been * performed per second since profiling started. If profiling has been * stopped, that moment in time is used for the calculation. Otherwise, * the current moment in time is used. * * @param type the type of database query to check. * @return the average number of queries of a certain typed performed per * second. */ public static double getQueriesPerSecond(int type) { long count, start, end; switch (type) { case SELECT: count = selectCount; start = startSelectTime; end = endSelectTime; break; case UPDATE: count = updateCount; start = startUpdateTime; end = endUpdateTime; break; case INSERT: count = insertCount; start = startInsertTime; end = endInsertTime; break; case DELETE: count = deleteCount; start = startDeleteTime; end = endDeleteTime; break; default: throw new IllegalArgumentException("Invalid type"); } // if no queries yet, return 0; if (count == 0) { return 0; } // If the profiling hasn't been stopped yet, we want to give // profiling values up to the current time instead. if (end == 0) { end = System.currentTimeMillis(); } // Compute the number of seconds double time = (end - start)/1000.0; // Finally, return the average. return count / time; } /** * Returns the average amount of time spent executing the specified type * of query. * * @param type the type of query. * @return a double representing the average time spent executing the type * of query. */ public static double getAverageQueryTime(int type) { long time, count; switch (type) { case SELECT: count = selectCount; time = totalSelectTime; break; case UPDATE: count = updateCount; time = totalUpdateTime; break; case INSERT: count = insertCount; time = totalInsertTime; break; case DELETE: count = deleteCount; time = totalDeleteTime; break; default: throw new IllegalArgumentException("Invalid type"); } if (count != 0) { return time/(double)count; } else { return 0.0; } } /** * Returns the total amount of time in milliseconds spent doing a particular * type of query. Note that this isn't necessarily representative of actual real * time since db queries often occur in parallel. * * @param type the type of query to check. * @return the number of milliseconds spent executing the specified type of * query. */ public static long getTotalQueryTime(int type) { switch (type) { case SELECT: return totalSelectTime; case UPDATE: return totalUpdateTime; case INSERT: return totalInsertTime; case DELETE: return totalDeleteTime; default: throw new IllegalArgumentException("Invalid type"); } } /** * Returns an array of sorted queries (as ProfiledConnectionEntry objects) by type * * @param type the type of query to check * @param sortByTime sort the resulting list by Time if true, * otherwise sort by count if false (default) * @return an array of ProfiledConnectionEntry objects */ public static ProfiledConnectionEntry[] getSortedQueries(int type, boolean sortByTime) { Hashtable queries; switch (type) { case SELECT: queries = selectQueries; break; case UPDATE: queries = updateQueries; break; case INSERT: queries = insertQueries; break; case DELETE: queries = deleteQueries; break; default: throw new IllegalArgumentException("Invalid type"); } ProfiledConnectionEntry[] result = new ProfiledConnectionEntry[queries.size()]; // no queries, return null set if (queries.size() < 1) { return null; } // since the values of the hashtable contain everything that // we need (including the sql statement), ignore the keys Enumeration e = queries.elements(); int c = 0; while (e.hasMoreElements()) { result[c++] = (ProfiledConnectionEntry) e.nextElement(); } quickSort(result, sortByTime, 0, result.length -1); return result; } /** * Reset all statistics. */ public static void resetStatistics() { startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = 0; endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0; insertCount = updateCount = selectCount = deleteCount = 0; totalInsertTime = totalUpdateTime = totalSelectTime = totalDeleteTime = 0; insertQueries.clear(); updateQueries.clear(); selectQueries.clear(); deleteQueries.clear(); } /** * @param entries entries * @param sortByTime sort by time if true, otherwise sort by count * @param first first index to sort on. Normally 0 * @param last last index to sort on. Normally length -1 */ private static void quickSort(ProfiledConnectionEntry[] entries, boolean sortByTime, int first, int last) { // do nothing if array contains fewer than two elements if (first >= last || entries.length < 2) { return; } swap(entries, first, (first+last)/2); int index = first; for (int i=first+1; i <= last; i++) { if (sortByTime && ((entries[first].totalTime/entries[first].count) < (entries[i].totalTime/entries[i].count))) { swap(entries, ++index, i); } else if (!sortByTime && entries[first].count < entries[i].count) { swap(entries, ++index, i); } } swap(entries, first, index); quickSort(entries, sortByTime, first, index-1); quickSort(entries, sortByTime, index+1, last); } private static void swap(Object[] list, int i, int j) { Object tmp = list[i]; list[i] = list[j]; list[j] = tmp; } private static String removeQueryValues(String _sql) { int length = _sql.length(); if (_sql.indexOf("=") == -1) { return _sql; } StringBuffer sql = new StringBuffer(_sql); boolean inValue = false; boolean afterEquals = false; boolean hasQuotes = false; int startValue = -1; int endValue = -1; int charRemoved = 0; for (int x = 0; x < length; x++) { char c = _sql.charAt(x); switch (c) { case '=': { if (!afterEquals) { afterEquals = true; } break; } case ' ': { if (!hasQuotes && inValue) { endValue = x; inValue = false; hasQuotes = false; afterEquals = false; } break; } case '\'': { if (afterEquals && !inValue) { startValue = x; inValue = true; hasQuotes = true; } else if (afterEquals && inValue && hasQuotes) { endValue = x+1; inValue = false; hasQuotes = false; afterEquals = false; } break; } case '-': { if (afterEquals && !inValue) { startValue = x; inValue = true; } break; } case '+': { if (afterEquals && !inValue) { startValue = x; inValue = true; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?