/* * Software Engineering Tools. * * $Id: Test60.java 15 2008-08-04 22:00:07Z hboutemy $ * * Copyright (c) 1997-2001 Joseph Kiniry * Copyright (c) 2000-2001 KindSoftware, LLC * Copyright (c) 1997-1999 California Institute of Technology * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Joseph Kiniry, KindSoftware, nor the * California Institute of Technology, nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KIND SOFTWARE OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package idebughc; import java.util.Hashtable; /** * <p> The core interface to gathering statistics. </p> * * <p> Users of IDebug wishing to keep statistics on their system need to * inherit from this abstract class and implement the protected methods. * The simplest means to collect statistics are to use a hashtable keyed on * statistic (since their hashCode is valid) and store Double objects * corresponding to the current value of that statistic. See * <code>idebughc.SimpleCollect</code> for an example of this * implementation which you can reuse. </p> * * @idea Alternative implementations that have some or all of the following * characteristics are encouraged. Ideas include collectors that: * <ul> * <li> send logging information at certain time intervals or trigger * values. </li> * <li> log statistic trace sets to do data analysis over long time * intervals. </li> * <li> compute means and variances so that accurate characterization of * the data is available. </li> * <li> detect significant changes in system behavior or performance and * can initiate early warning systems or preventive maintenence. </li> * <li> utilize system debugging context to log certain statistics and not * others (using the level and type of <code>Event</code> and the * <code>isValidCategory()</code> and <code>isValidLevel()</code> methods * herein). </li> * </ul> * * @version $Revision: 15 $ $Date: 2008-08-05 00:00:07 +0200 (Di, 05 Aug 2008) $ * @author Joseph R. Kiniry <joe@kindsoftware.com> * @history BON design for Dali by Donnie, Todd, and Joe. Adopted during * design phase of DALi into IDebug. * @see Statistic * @see idebug.SimpleCollect */ public abstract class Collect { // Attributes /** * <p> A <code>Hashtable</code> used to track statistics * definitions. </p> */ private Hashtable statistics; /** * <p> The <code>Debug</code> object associated with this * <code>Collect</code> object. </p> * * @modifies SINGLE-ASSIGNMENT */ private Debug debug; // Inherited Methods // Constructors /** * <p> Construct a new <code>Collect</code> class. </p> */ public Collect() { this.statistics = new Hashtable(); /** ensure [statistics_initialized] (statistics != null); **/ } // Public Methods /** * <p> Checks a debug instance to make sure its <code>collect</code> * attribute references this <code>Collect</code> object. </p> * * @concurrency CONCURRENT * @modifies QUERY * @param d the debug instance to check. */ public boolean checkDebugCollectRef(Debug d) { /** require [d_non_null] (d != null); **/ return (d.collect == this); /** ensure [result_correct] (Result == (d.collect == this)); **/ } /** * <p> Set the debug instance associated with this collect instance. * This method <strong>must</strong> be called with the correct debug * instance prior to using <strong>any</strong> of the methods of this * <code>Collect</code> instance. </p> * * @concurrency CONCURRENT * @modifies debug * @param d the debug object associated with this <code>Collect</code> * object. */ public final void setDebug(Debug d) { /** require [d_non_null] (d != null); [correct_debug_instance] checkDebugCollectRef(d); **/ debug = d; /** ensure [debug_valid] (debug == d); **/ } /** * <p> Register a statistic with the collector. </p> * * @concurrency CONCURRENT * @modifies statistics * @param statistic the statistic to register. */ public void register(Statistic statistic) { /** require [statistic_non_null] (statistic != null); [statistic_id_unchanged] checkStatisticID(statistic); **/ statistics.put(statistic, statistic); /** ensure [statistic_registered] isRegistered(statistic); **/ } /** * <p> Check the ID of a statistic and make sure that it hasn't changed * since it was registered. </p> * * @concurrency CONCURRENT * @modifies QUERY * @param statistic the statistic to check. */ public boolean checkStatisticID(Statistic statistic) { /** require [statistic_non_null] (statistic != null); **/ Object oldValue = statistics.get(statistic); if(oldValue != null) { // make sure value hasn't changed. return (oldValue == statistic); } return true; } /** * <p> Unregister a statistic with the collector. </p> * * @concurrency CONCURRENT * @modifies statistics * @param statistic the statistic to unregister. */ public void unregister(Statistic statistic) { /** require [statistic_non_null] (statistic != null); **/ statistics.remove(statistic); /** ensure [statistic_unregistered] !isRegistered(statistic); **/ } /** * <p> Check to see if a statistic is registered yet. </p> * * @param statistic the statistic to check. * @postcondition (Result == true) iff register(statistic) took place at * some point in time in the execution trace of this collect instance. */ public boolean isRegistered(Statistic statistic) { /** require [statistic_non_null] (statistic != null); **/ return(statistics.get(statistic) == statistic); } /** * <p> What is the current value for specific statistic? </p> * * @param statistic the statistic being modified. * @return the old value of the statistic. */ abstract public double currentValue(Statistic statistic); /** * <p> Report on a particular statistic. </p> * * @param statistic the statistic being reported on. * @return a report on the statistic, typically encapsulated in some type * of <code>Report</code> object or just a simple <code>String</code> * textual report. */ abstract public Object report(Statistic statistic); /** * <p> Report on all statistics. </p> * * @return a report on all statistics, typically encapsulated in some * type of Report object or just a simple String textual report. */ abstract public Object reportAll(); /** * <p> Increment a statistic by a specified value. </p> * * @param statistic the statistic being modified. * @param value the amount to increment the statistic. * @return the old value of the statistic. */ abstract public double increment(Statistic statistic, double value); /** * <p> Increment a statistic by the default value. </p> * * @param statistic the statistic being modified. * @return the old value of the statistic. */ abstract public double increment(Statistic statistic); /** * <p> Decrement a statistic by a specified value. </p> * * @param statistic the statistic being modified. * @param value the amount to decrement the statistic. * @return the old value of the statistic. */ abstract public double decrement(Statistic statistic, double value); /** * <p> Decrement a statistic by the default value. </p> * * @param statistic the statistic being modified. * @return the old value of the statistic. */ abstract public double decrement(Statistic statistic); /** * <p> Reset a statistic to the default start value. </p> * * @param statistic the statistic to reset. * @return the old value of the statistic. */ abstract public double reset(Statistic statistic); /** * <p> Set a statistic to a specific value. </p> * * @param statistic the statistic being modified. * @param value the new value of the statistic. * @return the old value of the statistic. */ abstract public double set(Statistic statistic, double value); // Protected Methods /** * <p> Tests to see if the current debug context is interested in a given * category. </p> * * @param category the category to inspect. * @return a boolean indicating if the category in question is valid at * this time for this context (i.e. debugging framework state, thread, * class invoking the method, etc.) * @see Context */ protected final boolean isValidCategory(String category) { /** require [category_non_null] (category != null); **/ return debug.debugUtilities.categoryTest(category); } /** * <p> Tests to see if the current debug context is interested in a given * level. </p> * * @param level the level to inspect. * @return a boolean indicating if the level in question is valid at this * time for this context (i.e. debugging framework state, thread, class * invoking the method, etc.) * @see Context */ protected final boolean isValidLevel(int level) { return debug.debugUtilities.levelTest(level); } // Package Methods // Private Methods } // end of class Collect /* * Local Variables: * Mode: Java * fill-column: 75 * End: */