17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate package com.sun.solaris.domain.pools;
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate import java.util.*;
337c478bd9Sstevel@tonic-gate import java.text.DecimalFormat;
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate import com.sun.solaris.service.logging.*;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /**
387c478bd9Sstevel@tonic-gate  * Contains information about statistics. An instance must only
397c478bd9Sstevel@tonic-gate  * contain Statistics of the same type.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate class StatisticList extends LinkedList
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	/**
447c478bd9Sstevel@tonic-gate 	 * The name of the statistic.
457c478bd9Sstevel@tonic-gate 	 */
467c478bd9Sstevel@tonic-gate 	private final String name;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	/**
497c478bd9Sstevel@tonic-gate 	 * The maximum number of samples to be stored.
507c478bd9Sstevel@tonic-gate 	 */
517c478bd9Sstevel@tonic-gate 	private final int maxSize;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 	/**
547c478bd9Sstevel@tonic-gate 	 * The list of StatisticListeners.
557c478bd9Sstevel@tonic-gate 	 */
567c478bd9Sstevel@tonic-gate 	private List listeners;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	/**
597c478bd9Sstevel@tonic-gate 	 * Statistically assess utilization.
607c478bd9Sstevel@tonic-gate 	 */
617c478bd9Sstevel@tonic-gate 	private StatisticOperations statisticOperations;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	/**
647c478bd9Sstevel@tonic-gate 	 * Constructor.
657c478bd9Sstevel@tonic-gate 	 */
StatisticList()667c478bd9Sstevel@tonic-gate 	public StatisticList()
677c478bd9Sstevel@tonic-gate 	{
687c478bd9Sstevel@tonic-gate 		this("default", 10);
697c478bd9Sstevel@tonic-gate 	}
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	/**
727c478bd9Sstevel@tonic-gate 	 * Constructor. Statistics will not be held for this set.
737c478bd9Sstevel@tonic-gate 	 *
747c478bd9Sstevel@tonic-gate 	 * @param name is the name of the contained statistics
757c478bd9Sstevel@tonic-gate 	 * @param size is the maximum number of statistics to hold
767c478bd9Sstevel@tonic-gate 	 */
StatisticList(String name, int size)777c478bd9Sstevel@tonic-gate 	public StatisticList(String name, int size)
787c478bd9Sstevel@tonic-gate 	{
797c478bd9Sstevel@tonic-gate 		this(name, size, false);
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	/**
837c478bd9Sstevel@tonic-gate 	 * Constructor.
847c478bd9Sstevel@tonic-gate 	 *
857c478bd9Sstevel@tonic-gate 	 * @param name is the name of the contained statistics
867c478bd9Sstevel@tonic-gate 	 * @param size is the maximum number of statistics to hold
877c478bd9Sstevel@tonic-gate 	 * @param doStats indicates whether or not statistics should
887c478bd9Sstevel@tonic-gate 	 * be calculated for the data.
897c478bd9Sstevel@tonic-gate 	 */
StatisticList(String name, int size, boolean doStats)907c478bd9Sstevel@tonic-gate 	public StatisticList(String name, int size, boolean doStats)
917c478bd9Sstevel@tonic-gate 	    throws IllegalArgumentException
927c478bd9Sstevel@tonic-gate 	{
937c478bd9Sstevel@tonic-gate 		super();
947c478bd9Sstevel@tonic-gate 		this.name = name;
957c478bd9Sstevel@tonic-gate 		if (size < 1)
967c478bd9Sstevel@tonic-gate 			throw new IllegalArgumentException("Size must be > 0");
977c478bd9Sstevel@tonic-gate 		this.maxSize = size;
987c478bd9Sstevel@tonic-gate 		listeners = new LinkedList();
997c478bd9Sstevel@tonic-gate 		if (doStats) {
1007c478bd9Sstevel@tonic-gate 			statisticOperations = new StatisticOperations(this);
1017c478bd9Sstevel@tonic-gate 			addStatisticListener(statisticOperations);
1027c478bd9Sstevel@tonic-gate 		}
1037c478bd9Sstevel@tonic-gate 	}
104*55fea89dSDan Cross 
1057c478bd9Sstevel@tonic-gate 	/**
1067c478bd9Sstevel@tonic-gate 	 * Return the name of the Statistics being sampled.
1077c478bd9Sstevel@tonic-gate 	 */
getName()1087c478bd9Sstevel@tonic-gate 	public String getName()
1097c478bd9Sstevel@tonic-gate 	{
1107c478bd9Sstevel@tonic-gate 		return (name);
111*55fea89dSDan Cross 	}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/**
1147c478bd9Sstevel@tonic-gate 	 * Return a "snapshot" which is the aggregation of all
1157c478bd9Sstevel@tonic-gate 	 * statistic records.
1167c478bd9Sstevel@tonic-gate 	 *
1177c478bd9Sstevel@tonic-gate 	 * @throws NoSuchElementException if there is an error
1187c478bd9Sstevel@tonic-gate 	 * accessing a list member.
1197c478bd9Sstevel@tonic-gate 	 */
getSnapshot()1207c478bd9Sstevel@tonic-gate 	public AggregateStatistic getSnapshot()
1217c478bd9Sstevel@tonic-gate 	    throws NoSuchElementException
1227c478bd9Sstevel@tonic-gate 	{
1237c478bd9Sstevel@tonic-gate 		return (getSnapshotForInterval(iterator(), null, null));
1247c478bd9Sstevel@tonic-gate 	}
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/**
1277c478bd9Sstevel@tonic-gate 	 * Return a "snapshot" of the data using the supplied
1287c478bd9Sstevel@tonic-gate 	 * iterator.
1297c478bd9Sstevel@tonic-gate 	 *
1307c478bd9Sstevel@tonic-gate 	 * @param it An iterator over the contained elements to be
1317c478bd9Sstevel@tonic-gate 	 * used as the basis for the snapshot.
1327c478bd9Sstevel@tonic-gate 	 * @throws NoSuchElementException if there is an error
1337c478bd9Sstevel@tonic-gate 	 * accessing a list member.
1347c478bd9Sstevel@tonic-gate 	 */
getSnapshot(Iterator it)1357c478bd9Sstevel@tonic-gate 	private AggregateStatistic getSnapshot(Iterator it)
1367c478bd9Sstevel@tonic-gate 	    throws NoSuchElementException
1377c478bd9Sstevel@tonic-gate 	{
1387c478bd9Sstevel@tonic-gate 		return (getSnapshotForInterval(it, null, null));
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/**
1427c478bd9Sstevel@tonic-gate 	 * Returns the aggregated value for the StatisticList only
1437c478bd9Sstevel@tonic-gate 	 * including samples which satisfy the start and end criteria.
1447c478bd9Sstevel@tonic-gate 	 *
1457c478bd9Sstevel@tonic-gate 	 * @param start start time or null if unspecified.
1467c478bd9Sstevel@tonic-gate 	 * @param end end time or null if unspecified.
1477c478bd9Sstevel@tonic-gate 	 * @throws NoSuchElementException if there is an error
1487c478bd9Sstevel@tonic-gate 	 * accessing a list member.
1497c478bd9Sstevel@tonic-gate 	 */
getSnapshotForInterval(Date start, Date end)1507c478bd9Sstevel@tonic-gate 	public AggregateStatistic getSnapshotForInterval(Date start,
1517c478bd9Sstevel@tonic-gate 	    Date end) throws NoSuchElementException
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	{
1547c478bd9Sstevel@tonic-gate 		return (getSnapshotForInterval(iterator(), start, end));
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	/**
1587c478bd9Sstevel@tonic-gate 	 * Returns the aggregated value for the StatisticList only
1597c478bd9Sstevel@tonic-gate 	 * including samples which satisfy the start and end criteria.
1607c478bd9Sstevel@tonic-gate 	 *
1617c478bd9Sstevel@tonic-gate 	 * @param it An iterator over the contained elements to be
1627c478bd9Sstevel@tonic-gate 	 * used as the basis for the snapshot.
1637c478bd9Sstevel@tonic-gate 	 * @param start start time or null if unspecified.
1647c478bd9Sstevel@tonic-gate 	 * @param end end time or null if unspecified.
1657c478bd9Sstevel@tonic-gate 	 * @throws NoSuchElementException if there is an error
1667c478bd9Sstevel@tonic-gate 	 * accessing a list member.
1677c478bd9Sstevel@tonic-gate 	 */
getSnapshotForInterval(Iterator it, Date start, Date end)1687c478bd9Sstevel@tonic-gate 	private AggregateStatistic getSnapshotForInterval(Iterator it,
1697c478bd9Sstevel@tonic-gate 	    Date start, Date end)
1707c478bd9Sstevel@tonic-gate 	{
1717c478bd9Sstevel@tonic-gate 		AggregateStatistic f = (AggregateStatistic) getFirst();
1727c478bd9Sstevel@tonic-gate 		return (f.getSnapshotForInterval(it, start, end));
1737c478bd9Sstevel@tonic-gate 	}
174*55fea89dSDan Cross 
1757c478bd9Sstevel@tonic-gate 	/**
1767c478bd9Sstevel@tonic-gate 	 * Add the supplied object to the list. If the list is full,
1777c478bd9Sstevel@tonic-gate 	 * remove the first entry before adding the new entry.
1787c478bd9Sstevel@tonic-gate 	 *
1797c478bd9Sstevel@tonic-gate 	 * @param o Object to add to the list.
1807c478bd9Sstevel@tonic-gate 	 */
add(Object o)181*55fea89dSDan Cross 	public boolean add(Object o)
1827c478bd9Sstevel@tonic-gate 	{
1837c478bd9Sstevel@tonic-gate 		boolean ret;
1847c478bd9Sstevel@tonic-gate 		if (size() == maxSize)
1857c478bd9Sstevel@tonic-gate 			removeFirst();
1867c478bd9Sstevel@tonic-gate 		ret = super.add(o);
1877c478bd9Sstevel@tonic-gate 		if (ret)
1887c478bd9Sstevel@tonic-gate 			notifyStatisticAdd((AggregateStatistic) o);
1897c478bd9Sstevel@tonic-gate 		return (ret);
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/**
1937c478bd9Sstevel@tonic-gate 	 * Remove the supplied object from the list.
1947c478bd9Sstevel@tonic-gate 	 *
1957c478bd9Sstevel@tonic-gate 	 * @param o Object to remove from the list.
1967c478bd9Sstevel@tonic-gate 	 */
remove(Object o)197*55fea89dSDan Cross 	public boolean remove(Object o)
1987c478bd9Sstevel@tonic-gate 	{
1997c478bd9Sstevel@tonic-gate 		boolean ret;
2007c478bd9Sstevel@tonic-gate 		ret = super.remove(o);
2017c478bd9Sstevel@tonic-gate 		if (ret)
2027c478bd9Sstevel@tonic-gate 			notifyStatisticRemove((AggregateStatistic) o);
2037c478bd9Sstevel@tonic-gate 		return (ret);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/**
2077c478bd9Sstevel@tonic-gate 	 * Removes and returns the first element from this list.
2087c478bd9Sstevel@tonic-gate 	 *
2097c478bd9Sstevel@tonic-gate 	 * @return the first element from this list.
2107c478bd9Sstevel@tonic-gate 	 * @throws	  NoSuchElementException if this list is empty.
2117c478bd9Sstevel@tonic-gate 	 */
removeFirst()2127c478bd9Sstevel@tonic-gate 	public Object removeFirst() {
2137c478bd9Sstevel@tonic-gate 		Object first = getFirst();
2147c478bd9Sstevel@tonic-gate 		remove(first);
2157c478bd9Sstevel@tonic-gate 		return (first);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/**
2197c478bd9Sstevel@tonic-gate 	 * Add a listener for StatisticEvents.
2207c478bd9Sstevel@tonic-gate 	 *
2217c478bd9Sstevel@tonic-gate 	 * @param l Listener to add.
2227c478bd9Sstevel@tonic-gate 	 */
addStatisticListener(StatisticListener l)2237c478bd9Sstevel@tonic-gate 	public void addStatisticListener(StatisticListener l) {
2247c478bd9Sstevel@tonic-gate 		listeners.add(l);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/**
2287c478bd9Sstevel@tonic-gate 	 * Remove a listener for StatisticEvents.
2297c478bd9Sstevel@tonic-gate 	 *
2307c478bd9Sstevel@tonic-gate 	 * @param l Listener to remove.
2317c478bd9Sstevel@tonic-gate 	 */
removeStatisticListener(StatisticListener l)2327c478bd9Sstevel@tonic-gate 	public void removeStatisticListener(StatisticListener l) {
2337c478bd9Sstevel@tonic-gate 		listeners.remove(l);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/**
2377c478bd9Sstevel@tonic-gate 	 * Notify all StatisticEvent listeners of a new Add event.
2387c478bd9Sstevel@tonic-gate 	 *
2397c478bd9Sstevel@tonic-gate 	 * @param s Event payload.
2407c478bd9Sstevel@tonic-gate 	 */
notifyStatisticAdd(AggregateStatistic s)2417c478bd9Sstevel@tonic-gate 	private void notifyStatisticAdd(AggregateStatistic s)
2427c478bd9Sstevel@tonic-gate 	{
2437c478bd9Sstevel@tonic-gate 		StatisticEvent e = new StatisticEvent(this,
2447c478bd9Sstevel@tonic-gate 		    StatisticEvent.ADD, s);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		Iterator listIt = listeners.iterator();
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		while (listIt.hasNext()) {
249*55fea89dSDan Cross 
2507c478bd9Sstevel@tonic-gate 			StatisticListener l = (StatisticListener)listIt.next();
2517c478bd9Sstevel@tonic-gate 			l.onStatisticAdd(e);
2527c478bd9Sstevel@tonic-gate 		}
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/**
2567c478bd9Sstevel@tonic-gate 	 * Notify all StatisticEvent listeners of a new Remove event.
2577c478bd9Sstevel@tonic-gate 	 *
2587c478bd9Sstevel@tonic-gate 	 * @param s Event payload.
2597c478bd9Sstevel@tonic-gate 	 */
notifyStatisticRemove(AggregateStatistic s)2607c478bd9Sstevel@tonic-gate 	private void notifyStatisticRemove(AggregateStatistic s)
2617c478bd9Sstevel@tonic-gate 	{
2627c478bd9Sstevel@tonic-gate 		StatisticEvent e = new StatisticEvent(this,
2637c478bd9Sstevel@tonic-gate 		    StatisticEvent.REMOVE, s);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		Iterator listIt = listeners.iterator();
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		while (listIt.hasNext()) {
268*55fea89dSDan Cross 
2697c478bd9Sstevel@tonic-gate 			StatisticListener l = (StatisticListener)listIt.next();
2707c478bd9Sstevel@tonic-gate 			l.onStatisticRemove(e);
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	/**
2757c478bd9Sstevel@tonic-gate 	 * Return true if the contents of the instance are
2767c478bd9Sstevel@tonic-gate 	 * statistically valid.
2777c478bd9Sstevel@tonic-gate 	 */
isValid()2787c478bd9Sstevel@tonic-gate 	boolean isValid()
2797c478bd9Sstevel@tonic-gate 	{
2807c478bd9Sstevel@tonic-gate 		return (statisticOperations.isValid());
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	/**
2847c478bd9Sstevel@tonic-gate 	 * Return the zone of control to which the supplied val
2857c478bd9Sstevel@tonic-gate 	 * belongs based on the target details in the supplied
2867c478bd9Sstevel@tonic-gate 	 * objective expression.
2877c478bd9Sstevel@tonic-gate 	 *
2887c478bd9Sstevel@tonic-gate 	 * @param kve Objective expression used to determine zone
2897c478bd9Sstevel@tonic-gate 	 * details.
2907c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed.
2917c478bd9Sstevel@tonic-gate 	 */
getZone(KVOpExpression kve, double val)2927c478bd9Sstevel@tonic-gate 	int getZone(KVOpExpression kve, double val)
2937c478bd9Sstevel@tonic-gate 	{
2947c478bd9Sstevel@tonic-gate 		return (statisticOperations.getZone(kve, val));
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/**
2987c478bd9Sstevel@tonic-gate 	 * Return the zone of control to which the supplied val
2997c478bd9Sstevel@tonic-gate 	 * belongs based on the mean of the sampled data.
3007c478bd9Sstevel@tonic-gate 	 *
3017c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed.
3027c478bd9Sstevel@tonic-gate 	 */
getZoneMean(double val)3037c478bd9Sstevel@tonic-gate 	int getZoneMean(double val)
3047c478bd9Sstevel@tonic-gate 	{
3057c478bd9Sstevel@tonic-gate 		return (statisticOperations.getZoneMean(val));
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	/**
3097c478bd9Sstevel@tonic-gate 	 * Return the difference (gap) between the target utilization
3107c478bd9Sstevel@tonic-gate 	 * expressed in the supplied objective expression and the
3117c478bd9Sstevel@tonic-gate 	 * supplied value.
3127c478bd9Sstevel@tonic-gate 	 *
3137c478bd9Sstevel@tonic-gate 	 * @param kve Objective expression used to determine target
3147c478bd9Sstevel@tonic-gate 	 * utilization details.
3157c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed.
3167c478bd9Sstevel@tonic-gate 	 */
getGap(KVOpExpression kve, double val)3177c478bd9Sstevel@tonic-gate 	double getGap(KVOpExpression kve, double val)
3187c478bd9Sstevel@tonic-gate 	{
3197c478bd9Sstevel@tonic-gate 		return (statisticOperations.getGap(kve, val));
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/**
3237c478bd9Sstevel@tonic-gate 	 * Clear all the data from the StatisticList and reset all the
3247c478bd9Sstevel@tonic-gate 	 * statistic counters.
3257c478bd9Sstevel@tonic-gate 	 */
clear()326*55fea89dSDan Cross 	public void clear()
3277c478bd9Sstevel@tonic-gate 	{
3287c478bd9Sstevel@tonic-gate 		if (statisticOperations != null) {
3297c478bd9Sstevel@tonic-gate 			removeStatisticListener(statisticOperations);
3307c478bd9Sstevel@tonic-gate 			statisticOperations = new StatisticOperations(this);
3317c478bd9Sstevel@tonic-gate 			addStatisticListener(statisticOperations);
3327c478bd9Sstevel@tonic-gate 		}
3337c478bd9Sstevel@tonic-gate 		super.clear();
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	/**
3377c478bd9Sstevel@tonic-gate 	 * Return a string which describes the zones for this set of
3387c478bd9Sstevel@tonic-gate 	 * data.
3397c478bd9Sstevel@tonic-gate 	 *
3407c478bd9Sstevel@tonic-gate 	 * @param kve The expression containing objectives.
3417c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed against objectives.
3427c478bd9Sstevel@tonic-gate 	 */
toZoneString(KVOpExpression kve, double val)3437c478bd9Sstevel@tonic-gate 	public String toZoneString(KVOpExpression kve, double val)
3447c478bd9Sstevel@tonic-gate 	{
3457c478bd9Sstevel@tonic-gate 		return (statisticOperations.toZoneString(kve, val));
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate /**
3507c478bd9Sstevel@tonic-gate  * Event class which describes modifications (Add, Remove) to a
3517c478bd9Sstevel@tonic-gate  * StatisticList instance.
3527c478bd9Sstevel@tonic-gate  */
3537c478bd9Sstevel@tonic-gate final class StatisticEvent extends EventObject
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate 	/**
3567c478bd9Sstevel@tonic-gate 	 * Identifier for an ADD event.
3577c478bd9Sstevel@tonic-gate 	 */
3587c478bd9Sstevel@tonic-gate 	public static final int ADD = 0x1;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/**
3617c478bd9Sstevel@tonic-gate 	 * Identifier for a REMOVE event.
3627c478bd9Sstevel@tonic-gate 	 */
3637c478bd9Sstevel@tonic-gate 	public static final int REMOVE = 0x2;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	/**
3667c478bd9Sstevel@tonic-gate 	 * The target of the event.
3677c478bd9Sstevel@tonic-gate 	 */
3687c478bd9Sstevel@tonic-gate 	private final AggregateStatistic target;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	/**
3717c478bd9Sstevel@tonic-gate 	 * The identifier of this event.
3727c478bd9Sstevel@tonic-gate 	 */
3737c478bd9Sstevel@tonic-gate 	private final int id;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	/**
3767c478bd9Sstevel@tonic-gate 	 * Constructor.
3777c478bd9Sstevel@tonic-gate 	 *
3787c478bd9Sstevel@tonic-gate 	 * @param source The source of the event.
3797c478bd9Sstevel@tonic-gate 	 * @param id The type of the event.
3807c478bd9Sstevel@tonic-gate 	 * @param target The target of the event.
3817c478bd9Sstevel@tonic-gate 	 */
StatisticEvent(Object source, int id, AggregateStatistic target)3827c478bd9Sstevel@tonic-gate 	public StatisticEvent(Object source, int id, AggregateStatistic target)
3837c478bd9Sstevel@tonic-gate 	{
3847c478bd9Sstevel@tonic-gate 		super(source);
3857c478bd9Sstevel@tonic-gate 		this.id = id;
3867c478bd9Sstevel@tonic-gate 		this.target = target;
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/**
3907c478bd9Sstevel@tonic-gate 	 * Return the target of the event.
3917c478bd9Sstevel@tonic-gate 	 */
getTarget()3927c478bd9Sstevel@tonic-gate 	public AggregateStatistic getTarget()
3937c478bd9Sstevel@tonic-gate 	{
3947c478bd9Sstevel@tonic-gate 		return (target);
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	/**
3987c478bd9Sstevel@tonic-gate 	 * Return the ID (type) of the event.
3997c478bd9Sstevel@tonic-gate 	 */
getID()4007c478bd9Sstevel@tonic-gate 	public int getID()
4017c478bd9Sstevel@tonic-gate 	{
4027c478bd9Sstevel@tonic-gate 		return (id);
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/**
4067c478bd9Sstevel@tonic-gate 	 * Return the source of the event. This is a typesafe
4077c478bd9Sstevel@tonic-gate 	 * alternative to using getSource().
4087c478bd9Sstevel@tonic-gate 	 */
getStatisticList()4097c478bd9Sstevel@tonic-gate 	public StatisticList getStatisticList()
4107c478bd9Sstevel@tonic-gate 	{
4117c478bd9Sstevel@tonic-gate 		return ((StatisticList) source);
4127c478bd9Sstevel@tonic-gate 	}
413*55fea89dSDan Cross 
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate /**
4177c478bd9Sstevel@tonic-gate  * The listener interface for receiving statistic events. The class
4187c478bd9Sstevel@tonic-gate  * that is interested in processing a statistic event implements this
4197c478bd9Sstevel@tonic-gate  * interface, and the object created with that class is registered
4207c478bd9Sstevel@tonic-gate  * with a component, using the component's addStatisticListener
4217c478bd9Sstevel@tonic-gate  * method. When the statistic event occurs, the relevant method in the
4227c478bd9Sstevel@tonic-gate  * listener object is invoked, and the StatisticEvent is passed to it.
4237c478bd9Sstevel@tonic-gate  */
4247c478bd9Sstevel@tonic-gate interface StatisticListener extends EventListener
4257c478bd9Sstevel@tonic-gate {
4267c478bd9Sstevel@tonic-gate 	/**
4277c478bd9Sstevel@tonic-gate 	 * Invoked when a statistic is added to the source
4287c478bd9Sstevel@tonic-gate 	 * StatisticList.
4297c478bd9Sstevel@tonic-gate 	 *
4307c478bd9Sstevel@tonic-gate 	 * @param e The event.
4317c478bd9Sstevel@tonic-gate 	 */
onStatisticAdd(StatisticEvent e)4327c478bd9Sstevel@tonic-gate 	public void onStatisticAdd(StatisticEvent e);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/**
4357c478bd9Sstevel@tonic-gate 	 * Invoked when a statistic is removed from the source
4367c478bd9Sstevel@tonic-gate 	 * StatisticList.
4377c478bd9Sstevel@tonic-gate 	 *
4387c478bd9Sstevel@tonic-gate 	 * @param e The event.
4397c478bd9Sstevel@tonic-gate 	 */
onStatisticRemove(StatisticEvent e)4407c478bd9Sstevel@tonic-gate 	public void onStatisticRemove(StatisticEvent e);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /**
4447c478bd9Sstevel@tonic-gate  * This class performs statistical calculations on a source
4457c478bd9Sstevel@tonic-gate  * StatisticList. Zones are regions in a set of samples which are set
4467c478bd9Sstevel@tonic-gate  * to be at 1, 2 and 3 standard deviations from the mean. ZONEC is
4477c478bd9Sstevel@tonic-gate  * closest to the center, with ZONEZ representing the region beyond
4487c478bd9Sstevel@tonic-gate  * ZONEA.
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate class StatisticOperations implements StatisticListener
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	/**
4537c478bd9Sstevel@tonic-gate 	 * Control zone C.
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	public static final int ZONEC = 0x00010;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/**
4587c478bd9Sstevel@tonic-gate 	 * Control zone B.
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 	public static final int ZONEB = 0x00100;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	/**
4637c478bd9Sstevel@tonic-gate 	 * Control zone A.
4647c478bd9Sstevel@tonic-gate 	 */
4657c478bd9Sstevel@tonic-gate 	public static final int ZONEA = 0x01000;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	/**
4687c478bd9Sstevel@tonic-gate 	 * Control zone Z.
4697c478bd9Sstevel@tonic-gate 	 */
4707c478bd9Sstevel@tonic-gate 	public static final int ZONEZ = 0x10000;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/**
4737c478bd9Sstevel@tonic-gate 	 * Direction from mean (used to test ZONELT and ZONEGT).
4747c478bd9Sstevel@tonic-gate 	 */
4757c478bd9Sstevel@tonic-gate 	public static final int ZONET = 0x00001;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/**
4787c478bd9Sstevel@tonic-gate 	 * Less than the mean.
4797c478bd9Sstevel@tonic-gate 	 */
4807c478bd9Sstevel@tonic-gate 	public static final int ZONELT = 0x00000;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	/**
4837c478bd9Sstevel@tonic-gate 	 * Greater than the mean.
4847c478bd9Sstevel@tonic-gate 	 */
4857c478bd9Sstevel@tonic-gate 	public static final int ZONEGT = 0x00001;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	/**
4887c478bd9Sstevel@tonic-gate 	 * The raw statistical data.
4897c478bd9Sstevel@tonic-gate 	 */
4907c478bd9Sstevel@tonic-gate 	private final StatisticList statistics;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	/**
4937c478bd9Sstevel@tonic-gate 	 * The mean of the samples.
4947c478bd9Sstevel@tonic-gate 	 */
4957c478bd9Sstevel@tonic-gate 	private double mean;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	/**
4987c478bd9Sstevel@tonic-gate 	 * The standard deviation of the samples.
4997c478bd9Sstevel@tonic-gate 	 */
5007c478bd9Sstevel@tonic-gate 	private double sd;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/**
5037c478bd9Sstevel@tonic-gate 	 * The total of the samples.
5047c478bd9Sstevel@tonic-gate 	 */
5057c478bd9Sstevel@tonic-gate 	private AggregateStatistic total;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	/**
5087c478bd9Sstevel@tonic-gate 	 * Constructs a new StatisticOperations object for working on
5097c478bd9Sstevel@tonic-gate 	 * the given statistic, whose values are in the given
5107c478bd9Sstevel@tonic-gate 	 * (modifiable) data set.
5117c478bd9Sstevel@tonic-gate 	 *
5127c478bd9Sstevel@tonic-gate 	 * @param statistics The statistics to operate on.
5137c478bd9Sstevel@tonic-gate 	 */
StatisticOperations(StatisticList statistics)5147c478bd9Sstevel@tonic-gate 	public StatisticOperations(StatisticList statistics)
5157c478bd9Sstevel@tonic-gate 	{
5167c478bd9Sstevel@tonic-gate 		this.statistics = statistics;
5177c478bd9Sstevel@tonic-gate 		total = new DoubleStatistic(new Double(0.0));
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	/**
5217c478bd9Sstevel@tonic-gate 	 * Calculate the standard deviation for the data held in the
5227c478bd9Sstevel@tonic-gate 	 * associated StatisticsList.
5237c478bd9Sstevel@tonic-gate 	 */
calc_sd()5247c478bd9Sstevel@tonic-gate 	private void calc_sd()
5257c478bd9Sstevel@tonic-gate 	{
5267c478bd9Sstevel@tonic-gate 		Iterator it;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		sd = 0;
5297c478bd9Sstevel@tonic-gate 		it = statistics.iterator();
5307c478bd9Sstevel@tonic-gate 		while (it.hasNext()) {
5317c478bd9Sstevel@tonic-gate 			Double val = (Double)((DoubleStatistic)
5327c478bd9Sstevel@tonic-gate 			    ((AggregateStatistic)it.next())).getValue();
533*55fea89dSDan Cross 
5347c478bd9Sstevel@tonic-gate 			sd += java.lang.Math.pow(val.doubleValue() - mean, 2);
5357c478bd9Sstevel@tonic-gate 		}
5367c478bd9Sstevel@tonic-gate 		sd /= statistics.size();
5377c478bd9Sstevel@tonic-gate 		sd = java.lang.Math.sqrt(sd);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/**
5417c478bd9Sstevel@tonic-gate 	 * Return a string which describes the zones for this set of
5427c478bd9Sstevel@tonic-gate 	 * data.
5437c478bd9Sstevel@tonic-gate 	 *
5447c478bd9Sstevel@tonic-gate 	 * @param kve The expression containing objectives.
5457c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed against objectives.
5467c478bd9Sstevel@tonic-gate 	 */
toZoneString(KVOpExpression kve, double val)5477c478bd9Sstevel@tonic-gate 	public String toZoneString(KVOpExpression kve, double val)
5487c478bd9Sstevel@tonic-gate 	{
5497c478bd9Sstevel@tonic-gate 		if (isValid()) {
5507c478bd9Sstevel@tonic-gate 			DecimalFormat f = new DecimalFormat("00.00");
5517c478bd9Sstevel@tonic-gate 			double target = kve.getValue();
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 			if (kve.getOp() == KVOpExpression.LT) {
5547c478bd9Sstevel@tonic-gate 				target -= 3 * sd;
5557c478bd9Sstevel@tonic-gate 			} else if (kve.getOp() == KVOpExpression.GT) {
5567c478bd9Sstevel@tonic-gate 				target += 3 * sd;
5577c478bd9Sstevel@tonic-gate 			}
5587c478bd9Sstevel@tonic-gate 			StringBuffer buf = new StringBuffer();
5597c478bd9Sstevel@tonic-gate 			buf.append(kve.toString());
5607c478bd9Sstevel@tonic-gate 			buf.append("\nsample = " + statistics.size());
5617c478bd9Sstevel@tonic-gate 			buf.append("\n\ttarget: " + f.format(target));
5627c478bd9Sstevel@tonic-gate 			buf.append("\n\tvalue: " + f.format(val));
5637c478bd9Sstevel@tonic-gate 			buf.append("\n\tsd: " + f.format(sd));
5647c478bd9Sstevel@tonic-gate 			buf.append("\n\tZones:");
5657c478bd9Sstevel@tonic-gate 			buf.append("\n\t\tC:" + f.format(target - sd));
5667c478bd9Sstevel@tonic-gate 			buf.append("-" + f.format(target + sd));
5677c478bd9Sstevel@tonic-gate 			buf.append("\n\t\tB:" + f.format(target - 2 * sd));
5687c478bd9Sstevel@tonic-gate 			buf.append("-" + f.format(target + 2 * sd));
5697c478bd9Sstevel@tonic-gate 			buf.append("\n\t\tA:" + f.format(target - 3 * sd));
5707c478bd9Sstevel@tonic-gate 			buf.append("-" + f.format(target + 3 * sd));
5717c478bd9Sstevel@tonic-gate 			return (buf.toString());
5727c478bd9Sstevel@tonic-gate 		} else {
5737c478bd9Sstevel@tonic-gate 			return ("Still sampling...");
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	/**
5797c478bd9Sstevel@tonic-gate 	 * Return a string which describes this instance.
5807c478bd9Sstevel@tonic-gate 	 */
toString()5817c478bd9Sstevel@tonic-gate 	public String toString()
5827c478bd9Sstevel@tonic-gate 	{
5837c478bd9Sstevel@tonic-gate 		DecimalFormat f = new DecimalFormat("00.00");
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 		if (isValid()) {
5867c478bd9Sstevel@tonic-gate 			return ("sample = " + statistics.size() +
5877c478bd9Sstevel@tonic-gate 			    "\n\tmean: " + f.format(mean) +
5887c478bd9Sstevel@tonic-gate 			    "\n\tsd: " + f.format(sd) +
5897c478bd9Sstevel@tonic-gate 			    "\n\tZones:" +
5907c478bd9Sstevel@tonic-gate 			    "\n\t\tC:" + f.format(mean - sd) +
5917c478bd9Sstevel@tonic-gate 			    "-" + f.format(mean + sd) +
5927c478bd9Sstevel@tonic-gate 			    "\n\t\tB:" + f.format(mean - 2 * sd) +
5937c478bd9Sstevel@tonic-gate 			    "-" + f.format(mean + 2 * sd) +
5947c478bd9Sstevel@tonic-gate 			    "\n\t\tA:" + f.format(mean - 3 * sd) +
5957c478bd9Sstevel@tonic-gate 			    "-" + f.format(mean + 3 * sd));
5967c478bd9Sstevel@tonic-gate 		} else {
5977c478bd9Sstevel@tonic-gate 			return ("Still sampling...");
5987c478bd9Sstevel@tonic-gate 		}
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	/**
6027c478bd9Sstevel@tonic-gate 	 * Return true if the data is normally distributed. This
6037c478bd9Sstevel@tonic-gate 	 * method currently just returns true if the sample size is >=
6047c478bd9Sstevel@tonic-gate 	 * 5. It could be extended to use a test of normality, for
6057c478bd9Sstevel@tonic-gate 	 * instance "Pearson's Chi-Squared Test" or "Shapiro-Wilks W
6067c478bd9Sstevel@tonic-gate 	 * Test".
6077c478bd9Sstevel@tonic-gate 	 */
isValid()6087c478bd9Sstevel@tonic-gate 	public boolean isValid()
6097c478bd9Sstevel@tonic-gate 	{
6107c478bd9Sstevel@tonic-gate 		if (statistics.size() >= 5)
6117c478bd9Sstevel@tonic-gate 			return (true);
6127c478bd9Sstevel@tonic-gate 		return (false);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	/**
6167c478bd9Sstevel@tonic-gate 	 * Calculate the statistical values for the associated
6177c478bd9Sstevel@tonic-gate 	 * samples. This method should be called when the sample
6187c478bd9Sstevel@tonic-gate 	 * population changes.
6197c478bd9Sstevel@tonic-gate 	 */
process()6207c478bd9Sstevel@tonic-gate 	private final void process()
6217c478bd9Sstevel@tonic-gate 	{
6227c478bd9Sstevel@tonic-gate 		mean = ((Double)((DoubleStatistic)total).getValue()).
6237c478bd9Sstevel@tonic-gate 		    doubleValue() / statistics.size();
6247c478bd9Sstevel@tonic-gate 		calc_sd();
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	/**
6287c478bd9Sstevel@tonic-gate 	 * Return the control zone for the supplied value using the
6297c478bd9Sstevel@tonic-gate 	 * information derived from the monitored statistics and the
6307c478bd9Sstevel@tonic-gate 	 * objective expressed in the supplied objective expression.
6317c478bd9Sstevel@tonic-gate 	 *
6327c478bd9Sstevel@tonic-gate 	 * @param kve The target utilization expression.
6337c478bd9Sstevel@tonic-gate 	 * @param val The value to be evaluated.
6347c478bd9Sstevel@tonic-gate 	 */
getZone(KVOpExpression kve, double val)6357c478bd9Sstevel@tonic-gate 	public int getZone(KVOpExpression kve, double val)
6367c478bd9Sstevel@tonic-gate 	{
6377c478bd9Sstevel@tonic-gate 		if (!isValid())
6387c478bd9Sstevel@tonic-gate 			return (StatisticOperations.ZONEC);
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 		double target = kve.getValue();
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 		if (kve.getOp() == KVOpExpression.LT) {
6437c478bd9Sstevel@tonic-gate 			target -= 3 * sd;
6447c478bd9Sstevel@tonic-gate 		} else if (kve.getOp() == KVOpExpression.GT) {
6457c478bd9Sstevel@tonic-gate 			target += 3 * sd;
6467c478bd9Sstevel@tonic-gate 		}
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 		return (getZone(target, val));
6497c478bd9Sstevel@tonic-gate 	}
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/**
6527c478bd9Sstevel@tonic-gate 	 * Return the control zone for the supplied value using the
6537c478bd9Sstevel@tonic-gate 	 * information derived from the monitored statistics.
6547c478bd9Sstevel@tonic-gate 	 *
6557c478bd9Sstevel@tonic-gate 	 * @param val The value to be evaluated.
6567c478bd9Sstevel@tonic-gate 	 */
getZoneMean(double val)6577c478bd9Sstevel@tonic-gate 	public int getZoneMean(double val)
6587c478bd9Sstevel@tonic-gate 	{
6597c478bd9Sstevel@tonic-gate 		if (!isValid())
6607c478bd9Sstevel@tonic-gate 			return (StatisticOperations.ZONEC);
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 		return (getZone(mean, val));
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	/**
6667c478bd9Sstevel@tonic-gate 	 * Return the control zone for the supplied value using the
6677c478bd9Sstevel@tonic-gate 	 * information derived from the supplied target.
6687c478bd9Sstevel@tonic-gate 	 *
6697c478bd9Sstevel@tonic-gate 	 * @param val The value to be evaluated.
6707c478bd9Sstevel@tonic-gate 	 */
getZone(double target, double val)6717c478bd9Sstevel@tonic-gate 	private int getZone(double target, double val)
6727c478bd9Sstevel@tonic-gate 	{
6737c478bd9Sstevel@tonic-gate 		if (!isValid())
6747c478bd9Sstevel@tonic-gate 			return (StatisticOperations.ZONEC);
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 		return ((val < target - 3 * sd) ?
6777c478bd9Sstevel@tonic-gate 		    ZONEZ | ZONELT : (val > target + 3 * sd) ?
6787c478bd9Sstevel@tonic-gate 		    ZONEZ | ZONEGT : (val < target - 2 * sd) ?
6797c478bd9Sstevel@tonic-gate 		    ZONEA | ZONELT : (val > target + 2 * sd) ?
6807c478bd9Sstevel@tonic-gate 		    ZONEA | ZONEGT : (val < target - sd) ?
6817c478bd9Sstevel@tonic-gate 		    ZONEB | ZONELT : (val > target + sd) ?
6827c478bd9Sstevel@tonic-gate 		    ZONEB | ZONEGT : (val < target) ?
6837c478bd9Sstevel@tonic-gate 		    ZONEC | ZONELT : ZONEC | ZONEGT);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	/**
6877c478bd9Sstevel@tonic-gate 	 * Return the difference (gap) between the target utilization
6887c478bd9Sstevel@tonic-gate 	 * expressed in the supplied objective expression and the
6897c478bd9Sstevel@tonic-gate 	 * supplied value.
6907c478bd9Sstevel@tonic-gate 	 *
6917c478bd9Sstevel@tonic-gate 	 * @param kve Objective expression used to determine target
6927c478bd9Sstevel@tonic-gate 	 * utilization details.
6937c478bd9Sstevel@tonic-gate 	 * @param val The value to be assessed.
6947c478bd9Sstevel@tonic-gate 	 */
getGap(KVOpExpression kve, double val)6957c478bd9Sstevel@tonic-gate 	public double getGap(KVOpExpression kve, double val)
6967c478bd9Sstevel@tonic-gate 	{
6977c478bd9Sstevel@tonic-gate 		if (!isValid())
6987c478bd9Sstevel@tonic-gate 			return (0.0);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		double target = kve.getValue();
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 		if (kve.getOp() == KVOpExpression.LT) {
7037c478bd9Sstevel@tonic-gate 			target -= 3 * sd;
7047c478bd9Sstevel@tonic-gate 		} else if (kve.getOp() == KVOpExpression.GT) {
7057c478bd9Sstevel@tonic-gate 			target += 3 * sd;
7067c478bd9Sstevel@tonic-gate 		}
7077c478bd9Sstevel@tonic-gate 		if (val - target < -100)
7087c478bd9Sstevel@tonic-gate 			return (-100);
7097c478bd9Sstevel@tonic-gate 		else if (val - target > 100)
7107c478bd9Sstevel@tonic-gate 			return (100);
7117c478bd9Sstevel@tonic-gate 		else
7127c478bd9Sstevel@tonic-gate 			return (val - target);
7137c478bd9Sstevel@tonic-gate 	}
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	/**
7167c478bd9Sstevel@tonic-gate 	 * Event handler for added statistics.
7177c478bd9Sstevel@tonic-gate 	 *
7187c478bd9Sstevel@tonic-gate 	 * @param e The event.
7197c478bd9Sstevel@tonic-gate 	 */
onStatisticAdd(StatisticEvent e)7207c478bd9Sstevel@tonic-gate 	public void onStatisticAdd(StatisticEvent e)
7217c478bd9Sstevel@tonic-gate 	{
7227c478bd9Sstevel@tonic-gate 		total = total.add(e.getTarget());
7237c478bd9Sstevel@tonic-gate 		process();
724*55fea89dSDan Cross 
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/**
7287c478bd9Sstevel@tonic-gate 	 * Event handler for removed statistics.
7297c478bd9Sstevel@tonic-gate 	 *
7307c478bd9Sstevel@tonic-gate 	 * @param e The event.
7317c478bd9Sstevel@tonic-gate 	 */
onStatisticRemove(StatisticEvent e)7327c478bd9Sstevel@tonic-gate 	public void onStatisticRemove(StatisticEvent e)
7337c478bd9Sstevel@tonic-gate 	{
7347c478bd9Sstevel@tonic-gate 		total = total.subtract(e.getTarget());
7357c478bd9Sstevel@tonic-gate 		process();
736*55fea89dSDan Cross 	}
7377c478bd9Sstevel@tonic-gate }
738