KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > monitor > GaugeMonitor


1 /*
2  * @(#)GaugeMonitor.java 1.73 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management.monitor;
9
10
11 // java imports
12
//
13
import java.util.Date JavaDoc;
14 import java.util.Timer JavaDoc;
15 import java.util.TimerTask JavaDoc;
16
17 // RI imports
18
//
19
import javax.management.ObjectName JavaDoc;
20 import javax.management.MBeanNotificationInfo JavaDoc;
21 import javax.management.AttributeNotFoundException JavaDoc;
22 import javax.management.InstanceNotFoundException JavaDoc;
23 import javax.management.MBeanException JavaDoc;
24 import javax.management.ReflectionException JavaDoc;
25
26 /**
27  * Defines a monitor MBean designed to observe the values of a gauge attribute.
28  *
29  * <P> A gauge monitor observes an attribute that is continuously
30  * variable with time. A gauge monitor sends notifications as
31  * follows:
32  *
33  * <UL>
34  *
35  * <LI> if the attribute value is increasing and becomes equal to or
36  * greater than the high threshold value, a {@link
37  * MonitorNotification#THRESHOLD_HIGH_VALUE_EXCEEDED threshold high
38  * notification} is sent. The notify high flag must be set to
39  * <CODE>true</CODE>
40  *
41  * <BR>Subsequent crossings of the high threshold value do not cause
42  * further notifications unless the attribute value becomes equal to
43  * or less than the low threshold value.
44  *
45  * <LI> if the attribute value is decreasing and becomes equal to or
46  * less than the low threshold value, a {@link
47  * MonitorNotification#THRESHOLD_LOW_VALUE_EXCEEDED threshold low
48  * notification} is sent. The notify low flag must be set to
49  * <CODE>true</CODE>.
50  *
51  * <BR>Subsequent crossings of the low threshold value do not cause
52  * further notifications unless the attribute value becomes equal to
53  * or greater than the high threshold value.
54  *
55  * </UL>
56  *
57  * This provides a hysteresis mechanism to avoid repeated triggering
58  * of notifications when the attribute value makes small oscillations
59  * around the high or low threshold value.
60  *
61  * <P> If the gauge difference mode is used, the value of the derived
62  * gauge is calculated as the difference between the observed gauge
63  * values for two successive observations.
64  *
65  * <BR>The derived gauge value (V[t]) is calculated using the following method:
66  * <UL>
67  * <LI>V[t] = gauge[t] - gauge[t-GP]
68  * </UL>
69  *
70  * This implementation of the gauge monitor requires the observed
71  * attribute to be of the type integer or floating-point
72  * (<CODE>Byte</CODE>, <CODE>Integer</CODE>, <CODE>Short</CODE>,
73  * <CODE>Long</CODE>, <CODE>Float</CODE>, <CODE>Double</CODE>).
74  *
75  * @version 1.73 05/18/04
76  * @author Sun Microsystems, Inc
77  *
78  * @since 1.5
79  */

80 public class GaugeMonitor extends Monitor JavaDoc implements GaugeMonitorMBean JavaDoc {
81
82
83     /*
84      * ------------------------------------------
85      * PRIVATE VARIABLES
86      * ------------------------------------------
87      */

88
89     private static final Integer JavaDoc INTEGER_ZERO = new Integer JavaDoc(0);
90
91     /**
92      * Gauge high threshold.
93      * <BR>The default value is a null Integer object.
94      */

95     private Number JavaDoc highThreshold = INTEGER_ZERO;
96
97     /**
98      * Gauge low threshold.
99      * <BR>The default value is a null Integer object.
100      */

101     private Number JavaDoc lowThreshold = INTEGER_ZERO;
102
103     /**
104      * Flag indicating if the gauge monitor notifies when exceeding
105      * the high threshold.
106      *
107      * <BR>The default value is set to <CODE>false</CODE>.
108      */

109     private boolean notifyHigh = false;
110
111     /**
112      * Flag indicating if the gauge monitor notifies when exceeding
113      * the low threshold.
114      *
115      * <BR>The default value is set to <CODE>false</CODE>.
116      */

117     private boolean notifyLow = false;
118
119     /**
120      * Flag indicating if the gauge difference mode is used. If the
121      * gauge difference mode is used, the derived gauge is the
122      * difference between two consecutive observed values. Otherwise,
123      * the derived gauge is directly the value of the observed
124      * attribute.
125      *
126      * <BR>The default value is set to <CODE>false</CODE>.
127      */

128     private boolean differenceMode = false;
129
130     /**
131      * Derived gauges.
132      * <BR>Each element in this array corresponds to an observed
133      * object in the list.
134      */

135     private Number JavaDoc derivedGauge[] = new Number JavaDoc[capacityIncrement];
136
137     /**
138      * Derived gauge timestamps.
139      * <BR>Each element in this array corresponds to an observed
140      * object in the list.
141      */

142     private long derivedGaugeTimestamp[] = new long[capacityIncrement];
143
144     /**
145      * Scan gauge values captured by the previous observation.
146      * <BR>Each element in this array corresponds to an observed
147      * object in the list.
148      */

149     private Number JavaDoc previousScanGauge[] = new Number JavaDoc[capacityIncrement];
150
151     /**
152      * This attribute is used to handle the hysteresis mechanism.
153      * <BR>Each element in this array corresponds to an observed
154      * object in the list.
155      */

156     private int status[] = new int[capacityIncrement];
157
158     /**
159      * This attribute is used to keep the derived gauge type.
160      * <BR>Each element in this array corresponds to an observed
161      * object in the list.
162      */

163     private int type[] = new int[capacityIncrement];
164
165     // Flags needed to implement the hysteresis mechanism.
166
//
167
private static final int RISING = 0;
168     private static final int FALLING = 1;
169     private static final int RISING_OR_FALLING = 2;
170
171     // Flags needed to keep trace of the derived gauge type.
172
// Integer + floating-point types are allowed.
173
//
174
private static final int INTEGER = 0;
175     private static final int BYTE = 1;
176     private static final int SHORT = 2;
177     private static final int LONG = 3;
178     private static final int FLOAT = 4;
179     private static final int DOUBLE = 5;
180
181     // New flags defining possible gauge monitor errors.
182

183     // Flag denoting that a notification has occurred after changing
184
// the high/low threshold. This flag is used to check that the
185
// high/low threshold type is the same as the gauge and that the
186
// threshold high value is greater than the threshold low value at
187
// the first notification time.
188
//
189
private static final int THRESHOLD_ERROR_NOTIFIED = 16;
190
191     /**
192      * Timer.
193      */

194     private Timer JavaDoc timer = null;
195
196
197
198     // TRACES & DEBUG
199
//---------------
200

201     String JavaDoc makeDebugTag() {
202         return "GaugeMonitor";
203     }
204
205     /*
206      * ------------------------------------------
207      * CONSTRUCTORS
208      * ------------------------------------------
209      */

210
211     /**
212      * Default constructor.
213      */

214     public GaugeMonitor() {
215       dbgTag = makeDebugTag();
216     }
217
218     /*
219      * ------------------------------------------
220      * PUBLIC METHODS
221      * ------------------------------------------
222      */

223
224     /**
225      * Starts the gauge monitor.
226      */

227     public void start() {
228
229         if (isTraceOn()) {
230             trace("start", "start the gauge monitor");
231         }
232
233     synchronized(this) {
234         if (isActive) {
235         if (isTraceOn()) {
236             trace("start", "the gauge monitor is already activated");
237         }
238
239         return;
240         }
241
242             isActive = true;
243
244             // Reset values.
245
//
246
for (int i = 0; i < elementCount; i++) {
247                 status[i] = RISING_OR_FALLING;
248                 previousScanGauge[i] = null;
249             }
250
251             // Start the AlarmClock.
252
//
253
timer = new Timer JavaDoc();
254             timer.schedule(new GaugeAlarmClock(this), getGranularityPeriod(),
255                getGranularityPeriod());
256     }
257     }
258
259     /**
260      * Stops the gauge monitor.
261      */

262     /* This method is not synchronized, because if it were there could
263        be a deadlock with a thread that attempted to get the lock on
264        the monitor before being interrupted or noticing that it had
265        been interrupted. */

266     public void stop() {
267     trace("stop", "stop the gauge monitor");
268
269     synchronized(this) {
270         if (!isActive) {
271         if (isTraceOn()) {
272             trace("stop", "the counter monitor is already started");
273         }
274
275         return;
276         }
277
278             isActive = false;
279
280             // Stop the AlarmClock.
281
//
282
if (timer != null) {
283                 timer.cancel();
284                 timer = null;
285             }
286     }
287     }
288
289     // GETTERS AND SETTERS
290
//--------------------
291

292     /**
293      * Sets the granularity period (in milliseconds).
294      * <BR>The default value of the granularity period is 10 seconds.
295      *
296      * @param period The granularity period value.
297      * @exception java.lang.IllegalArgumentException The granularity
298      * period is less than or equal to zero.
299      *
300      * @see Monitor#setGranularityPeriod(long)
301      */

302     public synchronized void setGranularityPeriod(long period)
303         throws IllegalArgumentException JavaDoc {
304         super.setGranularityPeriod(period);
305
306         // Reschedule timer task if timer is already running
307
//
308
if (isActive()) {
309         timer.cancel();
310         timer = new Timer JavaDoc();
311         timer.schedule(new GaugeAlarmClock(this), getGranularityPeriod(),
312                getGranularityPeriod());
313         }
314     }
315
316     /**
317      * Gets the derived gauge of the specified object, if this object is
318      * contained in the set of observed MBeans, or <code>null</code> otherwise.
319      *
320      * @param object the name of the MBean.
321      *
322      * @return The derived gauge of the specified object.
323      *
324      * @since.unbundled JMX 1.2
325      */

326     public synchronized Number JavaDoc getDerivedGauge(ObjectName JavaDoc object) {
327         int index = indexOf(object);
328         if (index != -1)
329             return derivedGauge[index];
330         else
331             return null;
332     }
333
334     /**
335      * Gets the derived gauge timestamp of the specified object, if
336      * this object is contained in the set of observed MBeans, or
337      * <code>null</code> otherwise.
338      *
339      * @param object the name of the MBean.
340      *
341      * @return The derived gauge timestamp of the specified object.
342      *
343      * @since.unbundled JMX 1.2
344      */

345     public synchronized long getDerivedGaugeTimeStamp(ObjectName JavaDoc object) {
346         int index = indexOf(object);
347         if (index != -1)
348             return derivedGaugeTimestamp[index];
349         else
350             return 0;
351     }
352
353     /**
354      * Returns the derived gauge of the first object in the set of
355      * observed MBeans.
356      *
357      * @return The derived gauge.
358      * @deprecated As of JMX 1.2, replaced by {@link #getDerivedGauge(ObjectName)}
359      */

360     @Deprecated JavaDoc
361     public synchronized Number JavaDoc getDerivedGauge() {
362         return derivedGauge[0];
363     }
364
365     /**
366      * Gets the derived gauge timestamp of the first object in the set
367      * of observed MBeans.
368      *
369      * @return The derived gauge timestamp.
370      * @deprecated As of JMX 1.2, replaced by
371      * {@link #getDerivedGaugeTimeStamp(ObjectName)}
372      */

373     @Deprecated JavaDoc
374     public synchronized long getDerivedGaugeTimeStamp() {
375         return derivedGaugeTimestamp[0];
376     }
377
378     /**
379      * Gets the high threshold value common to all observed MBeans.
380      *
381      * @return The high threshold value.
382      */

383     public synchronized Number JavaDoc getHighThreshold() {
384         return highThreshold;
385     }
386
387     /**
388      * Gets the low threshold value common to all observed MBeans.
389      *
390      * @return The low threshold value.
391      */

392     public synchronized Number JavaDoc getLowThreshold() {
393         return lowThreshold;
394     }
395
396     /**
397      * Sets the high and the low threshold values common to all
398      * observed MBeans.
399      *
400      * @param highValue The high threshold value.
401      * @param lowValue The low threshold value.
402      *
403      * @exception IllegalArgumentException The specified high/low
404      * threshold is null or the low threshold is greater than the high
405      * threshold or the high threshold and the low threshold are not
406      * of the same type.
407      */

408     public synchronized void setThresholds(Number JavaDoc highValue, Number JavaDoc lowValue)
409         throws IllegalArgumentException JavaDoc {
410
411         if ((highValue == null) || (lowValue == null)) {
412             throw new IllegalArgumentException JavaDoc("Null threshold value");
413         }
414         if (highValue.getClass() != lowValue.getClass()) {
415             throw new IllegalArgumentException JavaDoc("Different type " +
416                            "threshold values");
417         }
418
419         if (isFirstStrictlyGreaterThanLast(lowValue, highValue,
420                        highValue.getClass().getName())) {
421             throw new IllegalArgumentException JavaDoc("High threshold less than " +
422                            "low threshold");
423         }
424
425         highThreshold = highValue;
426         lowThreshold = lowValue;
427         for (int i = 0; i < elementCount; i++) {
428             resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);
429
430             // Reset values.
431
//
432
status[i] = RISING_OR_FALLING;
433         }
434     }
435
436     /**
437      * Gets the high notification's on/off switch value common to all
438      * observed MBeans.
439      *
440      * @see #setNotifyHigh
441      *
442      * @return <CODE>true</CODE> if the gauge monitor notifies when
443      * exceeding the high threshold, <CODE>false</CODE> otherwise.
444      */

445     public synchronized boolean getNotifyHigh() {
446         return notifyHigh;
447     }
448
449     /**
450      * Sets the high notification's on/off switch value common to all
451      * observed MBeans.
452      *
453      * @param value The high notification's on/off switch value.
454      *
455      * @see #getNotifyHigh
456      */

457     public synchronized void setNotifyHigh(boolean value) {
458         notifyHigh = value;
459     }
460
461     /**
462      * Gets the low notification's on/off switch value common to all
463      * observed MBeans.
464      *
465      * @return <CODE>true</CODE> if the gauge monitor notifies when
466      * exceeding the low threshold, <CODE>false</CODE> otherwise.
467      *
468      * @see #setNotifyLow
469      */

470     public synchronized boolean getNotifyLow() {
471         return notifyLow;
472     }
473
474     /**
475      * Sets the low notification's on/off switch value common to all
476      * observed MBeans.
477      *
478      * @param value The low notification's on/off switch value.
479      *
480      * @see #getNotifyLow
481      */

482     public synchronized void setNotifyLow(boolean value) {
483         notifyLow = value;
484     }
485
486     /**
487      * Gets the difference mode flag value common to all observed MBeans.
488      *
489      * @return <CODE>true</CODE> if the difference mode is used,
490      * <CODE>false</CODE> otherwise.
491      *
492      * @see #setDifferenceMode
493      */

494     public synchronized boolean getDifferenceMode() {
495         return differenceMode;
496     }
497
498     /**
499      * Sets the difference mode flag value common to all observed MBeans.
500      *
501      * @param value The difference mode flag value.
502      *
503      * @see #getDifferenceMode
504      */

505     public synchronized void setDifferenceMode(boolean value) {
506         differenceMode = value;
507
508         // Reset values.
509
//
510
for (int i = 0; i < elementCount; i++) {
511             status[i] = RISING_OR_FALLING;
512             previousScanGauge[i] = null;
513         }
514     }
515
516    /**
517      * Returns a <CODE>NotificationInfo</CODE> object containing the
518      * name of the Java class of the notification and the notification
519      * types sent by the gauge monitor.
520      */

521     public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
522         String JavaDoc[] types = { MonitorNotification.RUNTIME_ERROR,
523                             MonitorNotification.OBSERVED_OBJECT_ERROR,
524                             MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
525                             MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
526                             MonitorNotification.THRESHOLD_ERROR,
527                             MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED,
528                             MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED};
529         MBeanNotificationInfo JavaDoc[] notifsInfo = {
530         new MBeanNotificationInfo JavaDoc(types,
531                       "javax.management.monitor.MonitorNotification",
532                       "Notifications sent by the GaugeMonitor MBean")
533     };
534         return notifsInfo;
535     }
536
537     /*
538      * ------------------------------------------
539      * PRIVATE METHODS
540      * ------------------------------------------
541      */

542
543     /**
544      * Updates the derived gauge and the derived gauge timestamp attributes
545      * of the observed object at the specified index.
546      *
547      * @param scanGauge The value of the observed attribute.
548      * @param index The index of the observed object.
549      * @return <CODE>true</CODE> if the derived gauge value is valid,
550      * <CODE>false</CODE> otherwise. The derived gauge value is
551      * invalid when the differenceMode flag is set to
552      * <CODE>true</CODE> and it is the first notification (so we
553      * haven't 2 consecutive values to update the derived gauge).
554      */

555     private synchronized boolean updateDerivedGauge(Object JavaDoc scanGauge,
556                             int index) {
557
558         boolean is_derived_gauge_valid;
559
560         derivedGaugeTimestamp[index] = System.currentTimeMillis();
561
562         // The gauge difference mode is used.
563
//
564
if (differenceMode) {
565
566             // The previous scan gauge has been initialized.
567
//
568
if (previousScanGauge[index] != null) {
569                 setDerivedGaugeWithDifference((Number JavaDoc)scanGauge, index);
570                 is_derived_gauge_valid = true;
571             }
572             // The previous scan gauge has not been initialized.
573
// We cannot update the derived gauge...
574
//
575
else {
576                 is_derived_gauge_valid = false;
577             }
578             previousScanGauge[index] = (Number JavaDoc)scanGauge;
579         }
580         // The gauge difference mode is not used.
581
//
582
else {
583             derivedGauge[index] = (Number JavaDoc)scanGauge;
584             is_derived_gauge_valid = true;
585         }
586
587         return is_derived_gauge_valid;
588     }
589
590     /**
591      * Updates the notification attribute of the observed object at the
592      * specified index and notifies the listeners only once if the notify flag
593      * is set to <CODE>true</CODE>.
594      * @param index The index of the observed object.
595      */

596     private void updateNotifications(int index) {
597     boolean sendNotify = false;
598     String JavaDoc notifType = null;
599     long timeStamp = 0;
600     String JavaDoc msg = null;
601     Object JavaDoc derGauge = null;
602     Object JavaDoc trigger = null;
603
604         // Send high notification if notifyHigh is true.
605
// Send low notification if notifyLow is true.
606
//
607
synchronized(this) {
608         if (status[index] == RISING_OR_FALLING) {
609         if (isFirstGreaterThanLast(derivedGauge[index], highThreshold,
610                        type[index])) {
611             if (notifyHigh) {
612             sendNotify = true;
613             notifType =
614                 MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED;
615             timeStamp = derivedGaugeTimestamp[index];
616             msg = "";
617             derGauge = derivedGauge[index];
618             trigger = highThreshold;
619             }
620             status[index] = FALLING;
621         } else if (isFirstGreaterThanLast(lowThreshold,
622                           derivedGauge[index],
623                           type[index])) {
624             if (notifyLow) {
625             sendNotify = true;
626             notifType =
627                 MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED;
628             timeStamp = derivedGaugeTimestamp[index];
629             msg ="";
630             derGauge = derivedGauge[index];
631             trigger = lowThreshold;
632             }
633             status[index] = RISING;
634         }
635         } else {
636         if (status[index] == RISING) {
637             if (isFirstGreaterThanLast(derivedGauge[index],
638                            highThreshold,
639                            type[index])) {
640             if (notifyHigh) {
641                 sendNotify = true;
642                 notifType =
643                 MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED;
644                 timeStamp = derivedGaugeTimestamp[index];
645                 msg = "";
646                 derGauge = derivedGauge[index];
647                 trigger = highThreshold;
648             }
649             status[index] = FALLING;
650             }
651         } else if (status[index] == FALLING) {
652             if (isFirstGreaterThanLast(lowThreshold,
653                            derivedGauge[index],
654                            type[index])) {
655             if (notifyLow) {
656                 sendNotify = true;
657                 notifType =
658                 MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED;
659                 timeStamp = derivedGaugeTimestamp[index];
660                 msg = "";
661                 derGauge = derivedGauge[index];
662                 trigger = lowThreshold;
663             }
664             status[index] = RISING;
665             }
666         }
667         }
668     }
669
670     if (sendNotify) {
671         sendNotification(notifType, timeStamp, msg, derGauge, trigger, index);
672     }
673     }
674
675     /**
676      * Tests if the threshold high and threshold low are both of the
677      * same type as the gauge. Both integer and floating-point types
678      * are allowed.
679      *
680      * Note:
681      * If the optional lowThreshold or highThreshold have not been
682      * initialized, their default value is an Integer object with
683      * a value equal to zero.
684      *
685      * @param index The index of the observed object.
686      * @return <CODE>true</CODE> if type is the same,
687      * <CODE>false</CODE> otherwise.
688      */

689     private synchronized boolean isThresholdTypeValid(int index) {
690
691         switch(type[index]) {
692         case INTEGER:
693             return (((highThreshold == INTEGER_ZERO) ||
694              (highThreshold instanceof Integer JavaDoc)) &&
695             ((lowThreshold == INTEGER_ZERO) ||
696              (lowThreshold instanceof Integer JavaDoc)));
697         case BYTE:
698             return (((highThreshold == INTEGER_ZERO) ||
699              (highThreshold instanceof Byte JavaDoc)) &&
700             ((lowThreshold == INTEGER_ZERO) ||
701              (lowThreshold instanceof Byte JavaDoc)));
702         case SHORT:
703             return (((highThreshold == INTEGER_ZERO) ||
704              (highThreshold instanceof Short JavaDoc)) &&
705             ((lowThreshold == INTEGER_ZERO) ||
706              (lowThreshold instanceof Short JavaDoc)));
707         case LONG:
708             return (((highThreshold == INTEGER_ZERO) ||
709              (highThreshold instanceof Long JavaDoc)) &&
710             ((lowThreshold == INTEGER_ZERO) ||
711              (lowThreshold instanceof Long JavaDoc)));
712         case FLOAT:
713             return (((highThreshold == INTEGER_ZERO) ||
714              (highThreshold instanceof Float JavaDoc)) &&
715             ((lowThreshold == INTEGER_ZERO) ||
716              (lowThreshold instanceof Float JavaDoc)));
717         case DOUBLE:
718             return (((highThreshold == INTEGER_ZERO) ||
719              (highThreshold instanceof Double JavaDoc)) &&
720             ((lowThreshold == INTEGER_ZERO) ||
721              (lowThreshold instanceof Double JavaDoc)));
722         default:
723             // Should never occur...
724
if (isDebugOn()) {
725                 debug("isThresholdTypeValid", "The threshold type is invalid");
726             }
727         return false;
728         }
729     }
730
731     /**
732      * Sets the derived gauge when the differenceMode flag is set to
733      * <CODE>true</CODE>. Both integer and floating-point types are
734      * allowed.
735      *
736      * @param scanGauge The value of the observed attribute.
737      * @param index The index of the observed object.
738      */

739     private synchronized void setDerivedGaugeWithDifference(Number JavaDoc scanGauge,
740                                 int index) {
741     Number JavaDoc prev = previousScanGauge[index];
742     Number JavaDoc der;
743         switch (type[index]) {
744         case INTEGER:
745             der = new Integer JavaDoc(((Integer JavaDoc)scanGauge).intValue() -
746                   ((Integer JavaDoc)prev).intValue());
747             break;
748         case BYTE:
749             der = new Byte JavaDoc((byte)(((Byte JavaDoc)scanGauge).byteValue() -
750                   ((Byte JavaDoc)prev).byteValue()));
751             break;
752         case SHORT:
753             der = new Short JavaDoc((short)(((Short JavaDoc)scanGauge).shortValue() -
754                     ((Short JavaDoc)prev).shortValue()));
755             break;
756         case LONG:
757             der = new Long JavaDoc(((Long JavaDoc)scanGauge).longValue() -
758                ((Long JavaDoc)prev).longValue());
759             break;
760         case FLOAT:
761             der = new Float JavaDoc(((Float JavaDoc)scanGauge).floatValue() -
762                 ((Float JavaDoc)prev).floatValue());
763             break;
764         case DOUBLE:
765             der = new Double JavaDoc(((Double JavaDoc)scanGauge).doubleValue() -
766                  ((Double JavaDoc)prev).doubleValue());
767         default:
768             // Should never occur...
769
if (isDebugOn()) {
770                 debug("setDerivedGaugeWithDifference",
771               "the threshold type is invalid");
772             }
773         return;
774         }
775     derivedGauge[index] = der;
776     }
777
778     /**
779      * Tests if the first specified Number is greater than or equal to
780      * the last. Both integer and floating-point types are allowed.
781      *
782      * @param greater The first Number to compare with the second.
783      * @param less The second Number to compare with the first.
784      * @param type The number type.
785      * @return <CODE>true</CODE> if the first specified Number is
786      * greater than or equal to the last, <CODE>false</CODE>
787      * otherwise.
788      */

789     private boolean isFirstGreaterThanLast(Number JavaDoc greater,
790                        Number JavaDoc less, int type) {
791
792         switch(type) {
793         case INTEGER:
794         case BYTE:
795         case SHORT:
796         case LONG:
797             return (greater.longValue() >= less.longValue());
798         case FLOAT:
799         case DOUBLE:
800             return (greater.doubleValue() >= less.doubleValue());
801         default:
802             // Should never occur...
803
if (isDebugOn()) {
804                 debug("isFirstGreaterThanLast",
805               "the threshold type is invalid");
806             }
807         return false;
808         }
809     }
810
811     /**
812      * Tests if the first specified Number is strictly greater than the last.
813      * Both integer and floating-point types are allowed.
814      *
815      * @param greater The first Number to compare with the second.
816      * @param less The second Number to compare with the first.
817      * @param className The number class name.
818      * @return <CODE>true</CODE> if the first specified Number is
819      * strictly greater than the last, <CODE>false</CODE> otherwise.
820      */

821     private boolean isFirstStrictlyGreaterThanLast(Number JavaDoc greater,
822                            Number JavaDoc less,
823                            String JavaDoc className) {
824
825         if (className.equals("java.lang.Integer") ||
826             className.equals("java.lang.Byte") ||
827             className.equals("java.lang.Short") ||
828             className.equals("java.lang.Long")) {
829
830             return (greater.longValue() > less.longValue());
831         }
832         else if (className.equals("java.lang.Float") ||
833                  className.equals("java.lang.Double")) {
834
835             return (greater.doubleValue() > less.doubleValue());
836         }
837         else {
838             // Should never occur...
839
if (isDebugOn()) {
840                 debug("isFirstStrictlyGreaterThanLast",
841               "the threshold type is invalid");
842             }
843         return false;
844         }
845     }
846
847     /*
848      * ------------------------------------------
849      * PACKAGE METHODS
850      * ------------------------------------------
851      */

852
853     /**
854      * This method is called by the gauge monitor each time
855      * the granularity period has been exceeded.
856      * @param index The index of the observed object.
857      */

858     void notifyAlarmClock(int index) {
859     long timeStamp = 0;
860     String JavaDoc msg = null;
861     Object JavaDoc derGauge = null;
862
863         Object JavaDoc scan_gauge = null;
864         String JavaDoc notif_type = null;
865
866     synchronized(this) {
867             if (!isActive())
868         return;
869
870         // Check if the observed object and observed attribute are valid.
871
//
872

873         // Check that neither the observed object nor the observed
874
// attribute are null. If the observed object or observed
875
// attribute is null, this means that the monitor started
876
// before a complete initialization and nothing is done.
877
//
878
if ((getObservedObject(index) == null) ||
879         (getObservedAttribute() == null))
880         return;
881
882         // Check that the observed object is registered in the
883
// MBean server and that the observed attribute belongs to
884
// the observed object.
885
//
886
try {
887         scan_gauge = server.getAttribute(getObservedObject(index),
888                          getObservedAttribute());
889         if (scan_gauge == null)
890             return;
891         } catch (NullPointerException JavaDoc np_ex) {
892         if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
893             return;
894         else {
895             notif_type = MonitorNotification.RUNTIME_ERROR;
896             setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
897             msg =
898             "The gauge monitor must be registered in " +
899             "the MBean server.";
900         }
901         } catch (InstanceNotFoundException JavaDoc inf_ex) {
902         if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
903             return;
904         else {
905             notif_type = MonitorNotification.OBSERVED_OBJECT_ERROR;
906             setAlreadyNotified(index,
907                        OBSERVED_OBJECT_ERROR_NOTIFIED);
908             msg =
909             "The observed object must be registered in " +
910             "the MBean server.";
911         }
912         } catch (AttributeNotFoundException JavaDoc anf_ex) {
913         if (alreadyNotified(index,
914                     OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
915             return;
916         else {
917             notif_type =
918             MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
919             setAlreadyNotified(index,
920                        OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
921             msg =
922             "The observed attribute must be accessible in " +
923             "the observed object.";
924         }
925         } catch (MBeanException JavaDoc mb_ex) {
926         if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
927             return;
928         else {
929             notif_type = MonitorNotification.RUNTIME_ERROR;
930             setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
931             msg = mb_ex.getMessage();
932         }
933         } catch (ReflectionException JavaDoc ref_ex) {
934         if (alreadyNotified(index,
935                     OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
936             return;
937         else {
938             notif_type =
939             MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
940             setAlreadyNotified(index,
941                        OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
942             msg = ref_ex.getMessage();
943         }
944         }
945
946         if (msg == null) {
947                 // Check that the observed attribute is either of type
948
// "Integer" or "Float".
949
//
950
if (scan_gauge instanceof Integer JavaDoc) {
951                     type[index] = INTEGER;
952                 } else if (scan_gauge instanceof Byte JavaDoc) {
953                     type[index] = BYTE;
954                 } else if (scan_gauge instanceof Short JavaDoc) {
955                     type[index] = SHORT;
956                 } else if (scan_gauge instanceof Long JavaDoc) {
957                     type[index] = LONG;
958                 } else if (scan_gauge instanceof Float JavaDoc) {
959                     type[index] = FLOAT;
960                 } else if (scan_gauge instanceof Double JavaDoc) {
961                     type[index] = DOUBLE;
962                 } else {
963                     if (alreadyNotified(index,
964                     OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
965                         return;
966                     else {
967                         notif_type =
968                 MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR;
969                         setAlreadyNotified(index,
970                        OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
971                         msg =
972                 "The observed attribute type must be an " +
973                 "integer type or a floating-point type.";
974                     }
975                 }
976         }
977
978         if (msg == null) {
979                 // Check that threshold high and threshold low are of
980
// the same type as the gauge.
981
//
982
if (!isThresholdTypeValid(index)) {
983                     if (alreadyNotified(index, THRESHOLD_ERROR_NOTIFIED))
984                         return;
985                     else {
986                         notif_type = MonitorNotification.THRESHOLD_ERROR;
987                         setAlreadyNotified(index, THRESHOLD_ERROR_NOTIFIED);
988                         msg =
989                 "The threshold high and threshold low must be " +
990                 "of the same type as the gauge.";
991                     }
992                 }
993         }
994
995         if (msg == null) {
996
997         // Clear all already notified flags.
998
//
999
resetAllAlreadyNotified(index);
1000
1001        // Update the derived gauge attributes and check
1002
// the validity of the new value. The derived
1003
// gauge value is invalid when the differenceMode
1004
// flag is set to true and it is the first
1005
// notification (so we haven't 2 consecutive
1006
// values to update the derived gauge).
1007
//
1008
boolean is_derived_gauge_valid =
1009            updateDerivedGauge(scan_gauge, index);
1010
1011        // Notify the listeners if the updated derived
1012
// gauge value is valid.
1013
//
1014
if (is_derived_gauge_valid)
1015            updateNotifications(index);
1016
1017        } else {
1018
1019        // msg != null, will send an error notification
1020

1021        timeStamp = derivedGaugeTimestamp[index];
1022        derGauge = derivedGauge[index];
1023
1024        // Reset values.
1025
//
1026
status[index] = RISING_OR_FALLING;
1027        previousScanGauge[index] = null;
1028        }
1029    }
1030
1031    if (msg != null) {
1032        sendNotification(notif_type,
1033                 timeStamp,
1034                 msg,
1035                 derGauge,
1036                 null,
1037                 index);
1038    }
1039    }
1040
1041    /**
1042     * This method is called when adding a new observed object in the vector.
1043     * It updates all the gauge specific arrays.
1044     * @param index The index of the observed object.
1045     */

1046    synchronized void insertSpecificElementAt(int index) {
1047        // Update derivedGauge, derivedGaugeTimestamp, previousScanGauge,
1048
// status and type values.
1049

1050    if (index != elementCount)
1051        throw new Error JavaDoc("Internal error: index != elementCount");
1052
1053    if (elementCount >= derivedGauge.length) {
1054        derivedGauge = expandArray(derivedGauge);
1055        previousScanGauge = expandArray(previousScanGauge);
1056        derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
1057        status = expandArray(status);
1058        type = expandArray(type);
1059    }
1060
1061    derivedGauge[index] = INTEGER_ZERO;
1062    previousScanGauge[index] = null;
1063    derivedGaugeTimestamp[index] = System.currentTimeMillis();
1064    status[index] = RISING_OR_FALLING;
1065    type[index] = INTEGER;
1066    }
1067
1068    /**
1069     * This method is called when removing an observed object from the vector.
1070     * It updates all the gauge specific arrays.
1071     * @param index The index of the observed object.
1072     */

1073    synchronized void removeSpecificElementAt(int index) {
1074    if (index < 0 || index >= elementCount)
1075        return;
1076
1077        // Update derivedGauge, derivedGaugeTimestamp, previousScanGauge,
1078
// status and type arrays.
1079
//
1080
removeElementAt(derivedGauge, index);
1081        removeElementAt(previousScanGauge, index);
1082        removeElementAt(derivedGaugeTimestamp, index);
1083        removeElementAt(status, index);
1084        removeElementAt(type, index);
1085    }
1086
1087
1088    /**
1089     * GaugeAlarmClock inner class:
1090     * This class provides a simple implementation of an alarm clock MBean.
1091     * The aim of this MBean is to set up an alarm which wakes up the
1092     * gauge monitor every granularity period.
1093     */

1094
1095    private static class GaugeAlarmClock extends TimerTask JavaDoc {
1096
1097    GaugeMonitor JavaDoc listener = null;
1098
1099    /*
1100     * ------------------------------------------
1101     * CONSTRUCTORS
1102     * ------------------------------------------
1103     */

1104
1105    public GaugeAlarmClock(GaugeMonitor JavaDoc listener) {
1106        this.listener = listener;
1107    }
1108
1109    /*
1110     * ------------------------------------------
1111     * PUBLIC METHODS
1112     * ------------------------------------------
1113     */

1114
1115    /**
1116     * This method is called by the GaugeAlarmClock thread when it
1117     * is started.
1118     */

1119    public void run() {
1120        if (listener.isActive()) {
1121        for (int i = 0; i < listener.elementCount; i++) {
1122            listener.notifyAlarmClock(i);
1123        }
1124        }
1125    }
1126    }
1127}
1128
Popular Tags