⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profiledconnection.java

📁 java开发的一套非常好用的oa系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * $RCSfile: ProfiledConnection.java,v $
 * $Revision: 1.1.1.1 $
 * $Date: 2002/09/09 13:51: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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -