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 + -
显示快捷键?