ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/client/monitors/Disk__Monitor.java
Revision: 1.12
Committed: Wed Nov 7 17:55:40 2001 UTC (22 years, 6 months ago) by tdb
Branch: MAIN
Changes since 1.11: +8 -5 lines
Log Message:
Bug Fix for the following tracker ID on sourceforge:
  [ #479162 ] Disk Monitor - assumption of order

As stated in the above bug report, the state of a disk was stored using only
it's position in (ultimately) df's output. This position could change at runtime
which makes it not that reliable. The consequences of a change in the position
would not have been a disaster, but would have caused some confusion.

The key for storing a disks state is now the physical device name, as this is
will not change. The mount point was considered as the key, but it was decided
that this could change at runtime too.

File Contents

# Content
1 //---PACKAGE DECLARATION---
2 package uk.org.iscream.cms.server.client.monitors;
3
4 //---IMPORTS---
5 import java.util.HashMap;
6 import java.util.ArrayList;
7 import java.util.Set;
8 import java.util.Iterator;
9 import java.text.NumberFormat;
10 import uk.org.iscream.cms.server.client.*;
11 import uk.org.iscream.cms.server.core.*;
12 import uk.org.iscream.cms.server.util.*;
13 import uk.org.iscream.cms.server.componentmanager.*;
14
15 /**
16 * This Monitor watches the Disks for all machines
17 *
18 * @author $Author: tdb1 $
19 * @version $Id: Disk__Monitor.java,v 1.11 2001/11/07 16:44:11 tdb1 Exp $
20 */
21 public class Disk__Monitor extends MonitorSkeleton {
22
23 //---FINAL ATTRIBUTES---
24
25 /**
26 * The current CVS revision of this class
27 */
28 public final String REVISION = "$Revision: 1.11 $";
29
30 /**
31 * A description of this monitor
32 */
33 public final String DESC = "Monitors all host disks.";
34
35 //---STATIC METHODS---
36
37 //---CONSTRUCTORS---
38
39 //---PUBLIC METHODS---
40
41 /**
42 * Analyse a packet of data, and generate an alert if
43 * necessary.
44 *
45 * @param packet the XMLPacket to analyse
46 */
47 public void analysePacket(XMLPacket packet) {
48 String source = packet.getParam("packet.attributes.machine_name");
49 if (!_hosts.containsKey(source)) {
50 _hosts.put(source, new HashMap());
51 }
52
53 HashMap diskRegisters = (HashMap) _hosts.get(source);
54
55 // key prefix
56 String keyPrefix = "packet.disk.p";
57
58 // a temporary holder for all the disk attributes we find
59 ArrayList disks = new ArrayList();
60
61 // unfortunatly we need to check the whole packet
62 // to find the disks, and then get the data attributes
63 Set packetSet = packet.getSet();
64 Iterator i = packetSet.iterator();
65 while (i.hasNext()) {
66 String dataKey = (String) i.next();
67 if(dataKey.startsWith(keyPrefix)) {
68 if(!disks.contains(dataKey)) {
69 String diskNumber = "";
70
71 // pos is after "packet.disk.p"
72 int pos = keyPrefix.length();
73 while (dataKey.charAt(pos) != '.') {
74 diskNumber = diskNumber + dataKey.charAt(pos);
75 pos++;
76 }
77
78 // add the disk to our list, with the packet data
79
80 // used (we won't use this value - but we need it to forget about it ;)
81 disks.add(keyPrefix + diskNumber + ".attributes.used");
82
83 // device
84 disks.add(keyPrefix + diskNumber + ".attributes.name");
85 String device = packet.getParam(keyPrefix + diskNumber + ".attributes.name");
86 // mount point
87 disks.add(keyPrefix + diskNumber + ".attributes.mount");
88 String mount = packet.getParam(keyPrefix + diskNumber + ".attributes.mount");
89
90 // these next two will be used to calculate the %age
91 // total
92 disks.add(keyPrefix + diskNumber + ".attributes.kbytes");
93 String total = packet.getParam(keyPrefix + diskNumber + ".attributes.kbytes");
94 // available
95 disks.add(keyPrefix + diskNumber + ".attributes.avail");
96 String avail = packet.getParam(keyPrefix + diskNumber + ".attributes.avail");
97
98 // *** now process this disk ***
99
100 // check if we've seen this disk before on a previous run
101 // if not, we need to create a register for it
102 // nb. use the device as the key as this is unlikely to change,
103 // unlike diskNumber which could easily change
104 // (diskNumber is based on the order of df's output!)
105 if(!diskRegisters.containsKey(device)) {
106 diskRegisters.put(device, new Register(source, _name, mount));
107 }
108
109 // get the register for this disk
110 Register reg = (Register) diskRegisters.get(device);
111
112 // get the packet data
113 double diskTotal, diskAvail;
114 try {
115
116 if(total==null || avail==null) {
117 throw new NumberFormatException("Disk data invalid");
118 }
119 diskTotal = Double.parseDouble(total);
120 diskAvail = Double.parseDouble(avail);
121 } catch (NumberFormatException e) {
122 _logger.write(this.toString(), Logger.WARNING, "Received packet from "+source+" with bad disk information: "+e);
123 // don't try to continue and process, try next disk
124 break;
125 }
126
127 boolean useValue = false;
128 try {
129 String option = _cp.getProperty("Host." + source, "Monitor." + _name + ".thresholdMeasure");
130 if (option.equals("VALUE")) {
131 useValue = true;
132 }
133 } catch (PropertyNotFoundException e) {
134 // we default to percentage
135 }
136
137 // this bit determines if the disk check is a % check
138 // or a kb check
139 String type;
140 double curValue;
141 int newThreshold;
142 if(useValue) {
143 // kb disk available
144 curValue = diskAvail;
145 // negate check
146 newThreshold = checkAttributeThreshold(curValue, reg, true);
147 type = "kb";
148 } else {
149 // % disk in use
150 curValue = (1 - (diskAvail / diskTotal)) * 100;
151 // normal check
152 newThreshold = checkAttributeThreshold(curValue, reg, false);
153 type = "%";
154 }
155
156 // format the diskInUse to a String
157 NumberFormat nf = NumberFormat.getInstance();
158 nf.setMaximumFractionDigits(2);
159 nf.setMinimumFractionDigits(2);
160 String strCurValue = nf.format(curValue);
161
162 // say which disk had the problem
163 String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
164
165 processAlert(newThreshold, attributeName, reg, source, strCurValue);
166 }
167 }
168 }
169 }
170
171 /**
172 * Overrides the {@link java.lang.Object#toString() Object.toString()}
173 * method to provide clean logging (every class should have this).
174 *
175 * This uses the uk.org.iscream.cms.server.util.NameFormat class
176 * to format the toString()
177 *
178 * @return the name of this class and its CVS revision
179 */
180 public String toString() {
181 return FormatName.getName(
182 _name,
183 getClass().getName(),
184 REVISION);
185 }
186
187 /**
188 * return the String representation of what the monitor does
189 */
190 public String getDescription(){
191 return DESC;
192 }
193
194 //---PRIVATE METHODS---
195
196 /**
197 * Checks a piece of current data, and returns the
198 * threshold it breaches, if any.
199 *
200 * The option to negate the check can be used in
201 * situations where being *below* the threshold
202 * is an 'alertable' situation. In this specific
203 * case, we'd do this with kb disk checks.
204 *
205 * @param value the current value
206 * @param reg the Register for the host
207 * @param negateCheck whether to negate the check
208 * @return the threshold level breached, if any
209 */
210 private int checkAttributeThreshold(double diskInUse, Register reg, boolean negateCheck) {
211 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
212 if (reg.getThreshold(thresholdLevel) != -1.0) {
213 if(!negateCheck) {
214 // normal check - has the value gone *over* the threshold
215 if(((double) reg.getThreshold(thresholdLevel)) < diskInUse) {
216 return thresholdLevel;
217 }
218 }
219 else {
220 // negated check - has the value gone *under* the threshold
221 if(((double) reg.getThreshold(thresholdLevel)) > diskInUse) {
222 return thresholdLevel;
223 }
224 }
225 }
226 }
227 return Alert.thresholdNORMAL;
228 }
229
230 //---ACCESSOR/MUTATOR METHODS---
231
232 /**
233 * Returns a reference to a specific Queue for this
234 * monitor. This Queue returns only the data packets
235 * (based on type) that we want too look at.
236 *
237 * @return a reference to a Queue
238 */
239 protected Queue getQueue() {
240 return MonitorManager.getInstance().getDataQueue();
241 }
242
243 //---ATTRIBUTES---
244
245 /**
246 * This is the friendly identifier of the
247 * component this class is running in.
248 * eg, a Filter may be called "filter1",
249 * If this class does not have an owning
250 * component, a name from the configuration
251 * can be placed here. This name could also
252 * be changed to null for utility classes.
253 */
254 private String _name = "Disk";
255
256 /**
257 * A reference to the configuration proxy in use
258 */
259 private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
260
261 /**
262 * A HashMap of Registers (or groups of Registers), one
263 * for each host we're monitoring.
264 */
265 private HashMap _hosts = new HashMap();
266
267 //---STATIC ATTRIBUTES---
268
269 }