001: /**
002: * com.mckoi.util.Stats 04 Jul 2000
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.util;
024:
025: import java.util.*;
026: import java.io.PrintStream;
027:
028: /**
029: * An object that is used to store and update various stats.
030: * <p>
031: * NOTE: This object is thread safe.
032: *
033: * @author Tobias Downer
034: */
035:
036: public final class Stats {
037:
038: /**
039: * Where the stat properties are held.
040: */
041: private HashMap properties;
042:
043: /**
044: * Constructs the object.
045: */
046: public Stats() {
047: // We need lookup on this hash to be really quick, so load factor is
048: // low and initial capacity is high.
049: properties = new HashMap(250, 0.50f);
050: }
051:
052: /**
053: * Resets all stats that start with "{session}" to 0. This should be
054: * called when we are collecting stats over a given session and a session
055: * has finished.
056: */
057: public synchronized void resetSession() {
058: Set key_set = properties.keySet();
059: String[] keys = new String[key_set.size()];
060: int index = 0;
061: Iterator it = key_set.iterator();
062: while (it.hasNext()) {
063: keys[index] = (String) it.next();
064: ++index;
065: }
066:
067: // If key starts with a "{session}" then reset it to 0.
068: for (int i = 0; i < keys.length; ++i) {
069: if (keys[i].startsWith("{session}")) {
070: IntegerStat stat = (IntegerStat) properties
071: .get(keys[i]);
072: stat.value = 0;
073: }
074: }
075: }
076:
077: /**
078: * Adds the given value to a stat property.
079: */
080: public synchronized void add(int value, String stat_name) {
081: IntegerStat stat = (IntegerStat) properties.get(stat_name);
082: if (stat != null) {
083: stat.value += value;
084: } else {
085: stat = new IntegerStat();
086: stat.value = value;
087: properties.put(stat_name, stat);
088: }
089: }
090:
091: /**
092: * Increments a stat property. eg.
093: * stats.increment("File Hits");
094: */
095: public synchronized void increment(String stat_name) {
096: IntegerStat stat = (IntegerStat) properties.get(stat_name);
097: if (stat != null) {
098: ++stat.value;
099: } else {
100: stat = new IntegerStat();
101: stat.value = 1;
102: properties.put(stat_name, stat);
103: }
104: }
105:
106: /**
107: * Decrements a stat property.
108: */
109: public synchronized void decrement(String stat_name) {
110: IntegerStat stat = (IntegerStat) properties.get(stat_name);
111: if (stat != null) {
112: --stat.value;
113: } else {
114: stat = new IntegerStat();
115: stat.value = -1;
116: properties.put(stat_name, stat);
117: }
118: }
119:
120: /**
121: * Retrieves the current Object value of a stat property. Returns null if
122: * the stat wasn't found.
123: */
124: public synchronized Object get(String stat_name) {
125: IntegerStat stat = (IntegerStat) properties.get(stat_name);
126: if (stat != null) {
127: return new Long(stat.value);
128: }
129: return null;
130: }
131:
132: /**
133: * Sets the given stat name with the given value.
134: */
135: public synchronized void set(int value, String stat_name) {
136: IntegerStat stat = (IntegerStat) properties.get(stat_name);
137: if (stat != null) {
138: stat.value = value;
139: } else {
140: stat = new IntegerStat();
141: stat.value = value;
142: properties.put(stat_name, stat);
143: }
144: }
145:
146: /**
147: * Return a String array of all stat keys sorted in order from lowest to
148: * highest.
149: */
150: public synchronized String[] keyList() {
151: Set key_set = properties.keySet();
152:
153: String[] keys = new String[key_set.size()];
154: int index = 0;
155: Iterator it = key_set.iterator();
156: while (it.hasNext()) {
157: keys[index] = (String) it.next();
158: ++index;
159: }
160:
161: // Sort the keys
162: Arrays.sort(keys, STRING_COMPARATOR);
163:
164: return keys;
165: }
166:
167: /**
168: * Comparator for sorting the list of keys (for 1.1 implementation without
169: * Comparable String objects).
170: */
171: final static Comparator STRING_COMPARATOR = new Comparator() {
172: public int compare(Object ob1, Object ob2) {
173: return ((String) ob1).compareTo((String) ob2);
174: }
175: };
176:
177: /**
178: * Returns a String representation of the stat with the given key name.
179: */
180: public synchronized String statString(String key) {
181: IntegerStat stat = (IntegerStat) properties.get(key);
182: return Long.toString(stat.value);
183: }
184:
185: /**
186: * Returns a String that can be use to print out the values of all the stats.
187: */
188: public synchronized String toString() {
189:
190: String[] keys = keyList();
191:
192: StringBuffer buf = new StringBuffer();
193: for (int i = 0; i < keys.length; ++i) {
194: IntegerStat stat = (IntegerStat) properties.get(keys[i]);
195: buf.append(keys[i]);
196: buf.append(": ");
197: buf.append(stat.value);
198: buf.append('\n');
199: }
200:
201: return new String(buf);
202: }
203:
204: /**
205: * Outputs the stats to a print stream.
206: */
207: public synchronized void printTo(PrintStream out) {
208:
209: String[] keys = keyList();
210:
211: for (int i = 0; i < keys.length; ++i) {
212: IntegerStat stat = (IntegerStat) properties.get(keys[i]);
213: out.print(keys[i]);
214: out.print(": ");
215: out.println(stat.value);
216: }
217: }
218:
219: // ---------- Inner class ----------
220:
221: private static class IntegerStat {
222: long value;
223: }
224:
225: }
|