1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * ident	"%Z%%M%	%I%	%E% SMI"
27  */
28 
29 package com.sun.solaris.domain.pools;
30 
31 import java.math.BigInteger;
32 import java.util.HashMap;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.Iterator;
36 import com.sun.solaris.service.pools.Component;
37 import com.sun.solaris.service.pools.Resource;
38 import com.sun.solaris.service.pools.PoolsException;
39 import com.sun.solaris.service.pools.UnsignedInt64;
40 
41 /**
42  * This represents a monitored resource and the techniques used to
43  * monitor the resource.
44  */
45 class ResourceMonitor extends HashMap
46 {
47 	/**
48 	 * The monitored resource.
49 	 */
50 	private Resource target;
51 
52 	/**
53 	 * The size of the statistic buffer.
54 	 */
55 	private final int maxSize;
56 
57 	/**
58 	 * Cached list of components to be monitored.
59 	 */
60 	private LinkedList compList;
61 
62 	/**
63 	 * Constructor. No monitor target and a default buffer size of
64 	 * 50.
65 	 */
ResourceMonitor()66 	public ResourceMonitor()
67 	{
68 		this(null, 50);
69 	}
70 
71 	/**
72 	 * Constructor.
73 	 *
74 	 * @param target The resource to be monitored.
75 	 * @param maxSize The maximum number of samples to be held.
76 	 */
ResourceMonitor(Resource target, int maxSize)77 	public ResourceMonitor(Resource target, int maxSize)
78 	{
79 		super();
80 		this.target = target;
81 		this.maxSize = maxSize;
82 		compList = new LinkedList();
83 
84 	}
85 
86 	/**
87 	 * Initialize the resource monitor with it's list of
88 	 * components. Components which are off-line or powered-off
89 	 * cannot be monitored, so they should be removed from the
90 	 * list of components.
91 	 *
92 	 * @throws PoolsException if there is an error accessing the
93 	 * pool elements.
94 	 */
initialize()95 	public void initialize() throws PoolsException
96 	{
97 		compList.clear();
98 		List candidates = target.getComponents(null);
99 		Iterator candIt = candidates.iterator();
100 		while (candIt.hasNext()) {
101 			Component comp = (Component) candIt.next();
102 			String status = comp.getStringProperty("cpu.status");
103 			if (status.compareTo("off-line") != 0 &&
104 			    status.compareTo("powered-off") != 0)
105 				compList.add(comp);
106 		}
107 	}
108 
109 	/**
110 	 * Get the list of components which are actively monitored by
111 	 * this resource.
112 	 */
getComponents()113 	public List getComponents()
114 	{
115 		return ((List) compList.clone());
116 	}
117 
118 	/**
119 	 * Return the maximum number of samples this monitor will
120 	 * hold.
121 	 */
getMaxSampleSize()122 	public int getMaxSampleSize()
123 	{
124 		return (maxSize);
125 	}
126 
127 	/**
128 	 * Return the object which is being monitored.
129 	 */
getMonitored()130 	public Resource getMonitored()
131 	{
132 		return (target);
133 	}
134 
135 	/**
136 	 * Set the resource to be monitored. A resource target can
137 	 * only be set once, if you attempt to modify it then an
138 	 * IllegalArgumentException is thrown.
139 	 *
140 	 * @param target The resource to be monitored.
141 	 * @throws IllegalArgumentException if the target has already
142 	 * been set.
143 	 */
setResource(Resource target)144 	public void setResource(Resource target)
145 	{
146 		if (this.target != null)
147 			this.target = target;
148 		else
149 			throw new IllegalArgumentException("Once the target " +
150 			    "of a ResourceMonitor is set, it cannot be " +
151 			    "changed.");
152 	}
153 
154 	/**
155 	 * Return the name of the monitored object.
156 	 *
157 	 * @throws PoolsException if there is an error accessing the
158 	 * pool element.
159 	 */
getName()160 	public String getName() throws PoolsException
161 	{
162 		String type = target.getStringProperty("type");
163 		return (target.getStringProperty(type + ".name"));
164 	}
165 
166 	/**
167 	 * Update the derived statistics.
168 	 */
updateDerived()169 	public void updateDerived()
170 	{
171 		StatisticList util = (StatisticList) get("utilization");
172 		AggregateStatistic stat = calcDerivedStatistic("utilization");
173 		if (stat != null)
174 			util.add(stat);
175 	}
176 
177 	/**
178 	 * Get a derived statistic.
179 	 *
180 	 * @param name The name of the statistic to get.
181 	 */
getDerivedStatistic(String name)182 	public AggregateStatistic getDerivedStatistic(String name)
183 	{
184 		return ((AggregateStatistic)((StatisticList)get(name)).
185 		    getLast());
186 	}
187 
188 	/**
189 	 * Return the latest value of a derived statistic.
190 	 *
191 	 * @param name is the name of the derived statistic to be
192 	 * returned.
193 	 */
calcDerivedStatistic(String name)194 	private AggregateStatistic calcDerivedStatistic(String name)
195 	{
196 		/*
197 		 * The only statistic which can be obtained from this
198 		 * resource monitor is utilization. A utilization
199 		 * statistic actually represents a complex
200 		 * manipulation of several lower level
201 		 * statistics. This manipulation is performed here
202 		 * until a good interface can be thought through which
203 		 * best captures this abstraction.
204 		 */
205 		if (name.compareTo("utilization") != 0)
206 			throw new IllegalArgumentException("No such derived "
207 			    + "statistic: " + name);
208 		/*
209 		 * This statistic is based on lower level
210 		 * monotonically increasing numbers. The statistic can
211 		 * thus only be derived as an observation of the
212 		 * change in value over time of these values.
213 		 */
214 
215 		StatisticList first = (StatisticList) get("idle");
216 
217 		switch (first.size()) {
218 		case 0:
219 		case 1:
220 			return (null);
221 		default:
222 			BigInteger total = new BigInteger("0");
223 			double utilV = 0.0;
224 			double idleV = 0.0;
225 			LinkedList keys = new LinkedList(keySet());
226 			keys.remove("utilization");
227 			for (int i = 0; i < keys.size(); i++) {
228 				StatisticList sl = (StatisticList) get(keys.
229 				    get(i));
230 				AggregateStatistic sv1 = (AggregateStatistic)
231 				    sl.getLast();
232 				AggregateStatistic sv2 = (AggregateStatistic)
233 				    sl.get(sl.size() - 2);
234 				if (sl.getName().compareTo("idle") == 0)
235 					idleV = ((UnsignedInt64) sv1.
236 					    subtract(sv2).getValue()).
237 					    doubleValue();
238 				total = total.add((UnsignedInt64) sv1.
239 				    subtract(sv2).getValue());
240 			}
241 			utilV = 100 * ((total.doubleValue() - idleV) /
242 			    total.doubleValue());
243 			return (new DoubleStatistic(new Double(utilV),
244 				((AggregateStatistic)first.get(first.size() -
245 				2)).getStart(), ((AggregateStatistic)first.
246 				getLast()).getEnd()));
247 		}
248 	}
249 
resetData(String name)250 	void resetData(String name)
251 	{
252 		StatisticList sl = (StatisticList) get(name);
253 		sl.clear();
254 	}
255 }
256