KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)CounterMonitor.java 1.74 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 // java imports
11
//
12
import java.util.Date JavaDoc;
13 import java.util.Timer JavaDoc;
14 import java.util.TimerTask JavaDoc;
15
16 // jmx imports
17
//
18
import javax.management.ObjectName JavaDoc;
19 import javax.management.MBeanNotificationInfo JavaDoc;
20 import javax.management.AttributeNotFoundException JavaDoc;
21 import javax.management.InstanceNotFoundException JavaDoc;
22 import javax.management.MBeanException JavaDoc;
23 import javax.management.ReflectionException JavaDoc;
24
25 /**
26  * Defines a monitor MBean designed to observe the values of a counter
27  * attribute.
28  *
29  * <P> A counter monitor sends a {@link
30  * MonitorNotification#THRESHOLD_VALUE_EXCEEDED threshold
31  * notification} when the value of the counter reaches or exceeds a
32  * threshold known as the comparison level. The notify flag must be
33  * set to <CODE>true</CODE>.
34  *
35  * <P> In addition, an offset mechanism enables particular counting
36  * intervals to be detected. If the offset value is not zero,
37  * whenever the threshold is triggered by the counter value reaching a
38  * comparison level, that comparison level is incremented by the
39  * offset value. This is regarded as taking place instantaneously,
40  * that is, before the count is incremented. Thus, for each level,
41  * the threshold triggers an event notification every time the count
42  * increases by an interval equal to the offset value.
43  *
44  * <P> If the counter can wrap around its maximum value, the modulus
45  * needs to be specified. The modulus is the value at which the
46  * counter is reset to zero.
47  *
48  * <P> If the counter difference mode is used, the value of the
49  * derived gauge is calculated as the difference between the observed
50  * counter values for two successive observations. If this difference
51  * is negative, the value of the derived gauge is incremented by the
52  * value of the modulus. The derived gauge value (V[t]) is calculated
53  * using the following method:
54  *
55  * <UL>
56  * <LI>if (counter[t] - counter[t-GP]) is positive then
57  * V[t] = counter[t] - counter[t-GP]
58  * <LI>if (counter[t] - counter[t-GP]) is negative then
59  * V[t] = counter[t] - counter[t-GP] + MODULUS
60  * </UL>
61  *
62  * This implementation of the counter monitor requires the observed
63  * attribute to be of the type integer (<CODE>Byte</CODE>,
64  * <CODE>Integer</CODE>, <CODE>Short</CODE>, <CODE>Long</CODE>).
65  *
66  * @version 1.74 05/18/04
67  * @author Sun Microsystems, Inc
68  *
69  * @since 1.5
70  */

71 public class CounterMonitor extends Monitor JavaDoc implements CounterMonitorMBean JavaDoc {
72
73
74     /*
75      * ------------------------------------------
76      * PRIVATE VARIABLES
77      * ------------------------------------------
78      */

79
80     private static final Integer JavaDoc INTEGER_ZERO = new Integer JavaDoc(0);
81
82     /**
83      * Counter thresholds.
84      * <BR>Each element in this array corresponds to an observed
85      * object in the list.
86      */

87     private Number JavaDoc threshold[] = new Number JavaDoc[capacityIncrement];
88
89     /**
90      * Counter modulus.
91      * <BR>The default value is a null Integer object.
92      */

93     private Number JavaDoc modulus = INTEGER_ZERO;
94
95     /**
96      * Counter offset.
97      * <BR>The default value is a null Integer object.
98      */

99     private Number JavaDoc offset = INTEGER_ZERO;
100
101     /**
102      * Flag indicating if the counter monitor notifies when exceeding
103      * the threshold. The default value is set to
104      * <CODE>false</CODE>.
105      */

106     private boolean notify = false;
107
108     /**
109      * Flag indicating if the counter difference mode is used. If the
110      * counter difference mode is used, the derived gauge is the
111      * difference between two consecutive observed values. Otherwise,
112      * the derived gauge is directly the value of the observed
113      * attribute. The default value is set to <CODE>false</CODE>.
114      */

115     private boolean differenceMode = false;
116
117     /**
118      * Initial counter threshold. This value is used to initialize
119      * the threshold when a new object is added to the list and reset
120      * the threshold to its initial value each time the counter
121      * resets.
122      */

123     private Number JavaDoc initThreshold = INTEGER_ZERO;
124
125     /**
126      * Derived gauges.
127      *
128      * <BR>Each element in this array corresponds to an observed
129      * object in the list.
130      */

131     private Number JavaDoc derivedGauge[] = new Number JavaDoc[capacityIncrement];
132
133     /**
134      * Derived gauge timestamp.
135      * <BR>Each element in this array corresponds to an observed
136      * object in the list.
137      */

138     private long derivedGaugeTimestamp[] = new long[capacityIncrement];
139
140     /**
141      * Scan counter value captured by the previous observation.
142      * <BR>Each element in this array corresponds to an observed
143      * object in the list.
144      */

145     private Number JavaDoc previousScanCounter[] = new Number JavaDoc[capacityIncrement];
146
147     /**
148      * Flag indicating if the modulus has been exceeded by the
149      * threshold. This flag is used to reset the threshold once we
150      * are sure that the counter has been resetted.
151      * <BR>Each element in this array corresponds to an observed
152      * object in the list.
153      */

154     private boolean modulusExceeded[] = new boolean[capacityIncrement];
155
156     /**
157      * Derived gauge captured when the modulus has been exceeded by
158      * the threshold. This value is used to check if the counter has
159      * been resetted (in order to reset the threshold).
160      * <BR>Each element in this array corresponds to an observed
161      * object in the list.
162      */

163     private Number JavaDoc derivedGaugeExceeded[] = new Number JavaDoc[capacityIncrement];
164
165     /**
166      * This flag is used to notify only once between two granularity
167      * periods.
168      * <BR>Each element in this array corresponds to an observed
169      * object in the list.
170      */

171     private boolean eventAlreadyNotified[] = new boolean[capacityIncrement];
172
173     /**
174      * This attribute is used to keep the derived gauge type.
175      * <BR>Each element in this array corresponds to an observed
176      * object in the list.
177      */

178     private int type[] = new int[capacityIncrement];
179
180     // Flags needed to keep trace of the derived gauge type.
181
// Integer types only are allowed.
182
//
183
private static final int INTEGER = 0;
184     private static final int BYTE = 1;
185     private static final int SHORT = 2;
186     private static final int LONG = 3;
187
188     // New flags defining possible counter monitor errors.
189
// Flag denoting that a notification has occured after changing
190
// the threshold.
191
// This flag is used to check that the threshold, offset and
192
// modulus types are the same as the counter.
193
//
194
private static final int THRESHOLD_ERROR_NOTIFIED = 16;
195
196     /**
197      * Timer.
198      */

199     private Timer JavaDoc timer = null;
200
201
202     // TRACES & DEBUG
203
//---------------
204

205     String JavaDoc makeDebugTag() {
206         return "CounterMonitor";
207     }
208
209
210     /*
211      * ------------------------------------------
212      * CONSTRUCTORS
213      * ------------------------------------------
214      */

215
216     /**
217      * Default constructor.
218      */

219     public CounterMonitor() {
220     dbgTag = makeDebugTag();
221     }
222
223     /*
224      * ------------------------------------------
225      * PUBLIC METHODS
226      * ------------------------------------------
227      */

228
229     /**
230      * Allows the counter monitor MBean to perform any operations it
231      * needs before being unregistered by the MBean server.
232      *
233      * <P>Resets the threshold values.
234      *
235      * @exception java.lang.Exception
236      */

237     public void preDeregister() throws java.lang.Exception JavaDoc {
238
239         // Stop the CounterMonitor.
240
//
241
super.preDeregister();
242
243         if (isTraceOn()) {
244             trace("preDeregister", "reset the threshold values");
245         }
246
247         // Reset values for serialization.
248
//
249
synchronized (this) {
250         for (int i = 0; i < elementCount; i++) {
251         threshold[i] = initThreshold;
252         }
253     }
254     }
255
256     /**
257      * Starts the counter monitor.
258      */

259     public synchronized void start() {
260         if (isTraceOn()) {
261             trace("start", "start the counter monitor");
262         }
263
264     if (isActive()) {
265         if (isTraceOn()) {
266         trace("start", "the counter monitor is already activated");
267         }
268
269         return;
270     }
271
272     isActive = true;
273
274     // Reset values.
275
//
276
for (int i = 0; i < elementCount; i++) {
277         threshold[i] = initThreshold;
278         modulusExceeded[i] = false;
279         eventAlreadyNotified[i] = false;
280         previousScanCounter[i] = null;
281     }
282
283     // Start the timer.
284
//
285
timer = new Timer JavaDoc();
286     timer.schedule(new CounterAlarmClock(this), getGranularityPeriod(),
287                getGranularityPeriod());
288     }
289
290     /**
291      * Stops the counter monitor.
292      *
293      * This method is not synchronized, because if it were there could
294      * be a deadlock with a thread that attempted to get the lock on
295      * the monitor before being interrupted or noticing that it had
296      * been interrupted.
297      */

298     public synchronized void stop() {
299         if (isTraceOn()) {
300             trace("stop", "stop the counter monitor");
301         }
302
303     if (isTraceOn()) {
304         trace("stop", "the counter monitor is not started");
305
306         return;
307     }
308
309     isActive = false;
310
311     // Stop the timer.
312
//
313
if (timer != null) {
314         timer.cancel();
315         timer = null;
316     }
317     }
318
319     // GETTERS AND SETTERS
320
//--------------------
321

322     /**
323      * Sets the granularity period (in milliseconds).
324      * <BR>The default value of the granularity period is 10 seconds.
325      *
326      * @param period The granularity period value.
327      * @exception java.lang.IllegalArgumentException The granularity
328      * period is less than or equal to zero.
329      *
330      * @see Monitor#setGranularityPeriod(long)
331      */

332     public synchronized void setGranularityPeriod(long period)
333         throws IllegalArgumentException JavaDoc {
334     super.setGranularityPeriod(period);
335
336     // Reschedule timer task if timer is already running
337
//
338
if (isActive()) {
339         timer.cancel();
340         timer = new Timer JavaDoc();
341         timer.schedule(new CounterAlarmClock(this),
342                getGranularityPeriod(), getGranularityPeriod());
343     }
344     }
345
346     /**
347      * Gets the derived gauge of the specified object, if this object is
348      * contained in the set of observed MBeans, or <code>null</code> otherwise.
349      *
350      * @param object the name of the object whose derived gauge is to
351      * be returned.
352      *
353      * @return The derived gauge of the specified object.
354      *
355      * @since.unbundled JMX 1.2
356      */

357     public synchronized Number JavaDoc getDerivedGauge(ObjectName JavaDoc object) {
358     int index = indexOf(object);
359     if (index != -1)
360         return derivedGauge[index];
361     else
362         return null;
363     }
364
365     /**
366      * Gets the derived gauge timestamp of the specified object, if
367      * this object is contained in the set of observed MBeans, or
368      * <code>null</code> otherwise.
369      *
370      * @param object the name of the object whose derived gauge
371      * timestamp is to be returned.
372      *
373      * @return The derived gauge timestamp of the specified object.
374      *
375      * @since.unbundled JMX 1.2
376      */

377     public synchronized long getDerivedGaugeTimeStamp(ObjectName JavaDoc object) {
378     int index = indexOf(object);
379     if (index != -1)
380         return derivedGaugeTimestamp[index];
381     else
382         return 0;
383     }
384
385     /**
386      * Gets the current threshold value of the specified object, if
387      * this object is contained in the set of observed MBeans, or
388      * <code>null</code> otherwise.
389      *
390      * @param object the name of the object whose threshold is to be
391      * returned.
392      *
393      * @return The threshold value of the specified object.
394      *
395      * @see #setThreshold
396      *
397      * @since.unbundled JMX 1.2
398      */

399     public synchronized Number JavaDoc getThreshold(ObjectName JavaDoc object) {
400     int index = indexOf(object);
401     if (index != -1)
402         return threshold[index];
403     else
404         return null;
405     }
406
407     /**
408      * Gets the initial threshold value common to all observed objects.
409      *
410      * @return The initial threshold.
411      *
412      * @see #setInitThreshold
413      *
414      * @since.unbundled JMX 1.2
415      */

416     public synchronized Number JavaDoc getInitThreshold() {
417         return initThreshold;
418     }
419
420     /**
421      * Sets the initial threshold value common to all observed objects.
422      *
423      * <BR>The current threshold of every object in the set of
424      * observed MBeans is updated consequently.
425      *
426      * @param value The initial threshold value.
427      * @exception java.lang.IllegalArgumentException The specified
428      * threshold is null or the threshold value is less than zero.
429      *
430      * @see #getInitThreshold
431      *
432      * @since.unbundled JMX 1.2
433      */

434     public synchronized void setInitThreshold(Number JavaDoc value)
435         throws IllegalArgumentException JavaDoc {
436
437         if (value == null) {
438             throw new IllegalArgumentException JavaDoc("Null threshold");
439         }
440         if (value.longValue() < 0L) {
441             throw new IllegalArgumentException JavaDoc("Negative threshold");
442         }
443
444     initThreshold = value;
445     for (int i = 0; i < elementCount; i++) {
446         threshold[i] = value;
447         resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);
448
449             // Reset values.
450
//
451
modulusExceeded[i] = false;
452             eventAlreadyNotified[i] = false;
453         }
454     }
455
456     /**
457      * Returns the derived gauge of the first object in the set of
458      * observed MBeans.
459      *
460      * @return The derived gauge.
461      * @deprecated As of JMX 1.2, replaced by {@link #getDerivedGauge(ObjectName)}
462      */

463     @Deprecated JavaDoc
464     public synchronized Number JavaDoc getDerivedGauge() {
465         return derivedGauge[0];
466     }
467
468     /**
469      * Gets the derived gauge timestamp of the first object in the set
470      * of observed MBeans.
471      *
472      * @return The derived gauge timestamp.
473      * @deprecated As of JMX 1.2, replaced by
474      * {@link #getDerivedGaugeTimeStamp(ObjectName)}
475      */

476     @Deprecated JavaDoc
477     public synchronized long getDerivedGaugeTimeStamp() {
478         return derivedGaugeTimestamp[0];
479     }
480
481     /**
482      * Gets the threshold value of the first object in the set of
483      * observed MBeans.
484      *
485      * @return The threshold value.
486      *
487      * @see #setThreshold(Number)
488      *
489      * @deprecated As of JMX 1.2, replaced by {@link #getThreshold(ObjectName)}
490      */

491     @Deprecated JavaDoc
492     public synchronized Number JavaDoc getThreshold() {
493         return threshold[0];
494     }
495
496     /**
497      * Sets the initial threshold value.
498      *
499      * @param value The initial threshold value.
500      * @exception IllegalArgumentException The specified threshold is
501      * null or the threshold value is less than zero.
502      *
503      * @see #getThreshold()
504      *
505      * @deprecated As of JMX 1.2, replaced by {@link #setInitThreshold}
506      */

507     @Deprecated JavaDoc
508     public synchronized void setThreshold(Number JavaDoc value)
509         throws IllegalArgumentException JavaDoc {
510     setInitThreshold(value);
511     }
512
513     /**
514      * Gets the offset value common to all observed MBeans.
515      *
516      * @return The offset value.
517      *
518      * @see #setOffset
519      */

520     public synchronized Number JavaDoc getOffset() {
521         return offset;
522     }
523
524     /**
525      * Sets the offset value common to all observed MBeans.
526      *
527      * @param value The offset value.
528      * @exception java.lang.IllegalArgumentException The specified
529      * offset is null or the offset value is less than zero.
530      *
531      * @see #getOffset
532      */

533     public synchronized void setOffset(Number JavaDoc value)
534         throws IllegalArgumentException JavaDoc {
535
536         if (value == null) {
537             throw new IllegalArgumentException JavaDoc("Null offset");
538         }
539         if (value.longValue() < 0L) {
540             throw new IllegalArgumentException JavaDoc("Negative offset");
541         }
542
543     offset = value;
544     for (int i = 0; i < elementCount; i++) {
545         resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);
546     }
547     }
548
549     /**
550      * Gets the modulus value common to all observed MBeans.
551      *
552      * @see #setModulus
553      *
554      * @return The modulus value.
555      */

556     public synchronized Number JavaDoc getModulus() {
557         return modulus;
558     }
559
560     /**
561      * Sets the modulus value common to all observed MBeans.
562      *
563      * @param value The modulus value.
564      * @exception java.lang.IllegalArgumentException The specified
565      * modulus is null or the modulus value is less than zero.
566      *
567      * @see #getModulus
568      */

569     public synchronized void setModulus(Number JavaDoc value)
570         throws IllegalArgumentException JavaDoc {
571
572         if (value == null) {
573             throw new IllegalArgumentException JavaDoc("Null modulus");
574         }
575         if (value.longValue() < 0L) {
576             throw new IllegalArgumentException JavaDoc("Negative modulus");
577         }
578
579         modulus = value;
580         for (int i = 0; i < elementCount; i++) {
581         resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);
582
583             // Reset values.
584
//
585
modulusExceeded[i] = false;
586         }
587     }
588
589     /**
590      * Gets the notification's on/off switch value common to all
591      * observed MBeans.
592      *
593      * @return <CODE>true</CODE> if the counter monitor notifies when
594      * exceeding the threshold, <CODE>false</CODE> otherwise.
595      *
596      * @see #setNotify
597      */

598     public synchronized boolean getNotify() {
599         return notify;
600     }
601
602     /**
603      * Sets the notification's on/off switch value common to all
604      * observed MBeans.
605      *
606      * @param value The notification's on/off switch value.
607      *
608      * @see #getNotify
609      */

610     public synchronized void setNotify(boolean value) {
611         notify = value;
612     }
613
614     /**
615      * Gets the difference mode flag value common to all observed MBeans.
616      *
617      * @return <CODE>true</CODE> if the difference mode is used,
618      * <CODE>false</CODE> otherwise.
619      *
620      * @see #setDifferenceMode
621      */

622     public synchronized boolean getDifferenceMode() {
623         return differenceMode;
624     }
625
626     /**
627      * Sets the difference mode flag value common to all observed MBeans.
628      *
629      * @param value The difference mode flag value.
630      *
631      * @see #getDifferenceMode
632      */

633     public synchronized void setDifferenceMode(boolean value) {
634         differenceMode = value;
635
636         for (int i = 0; i < elementCount; i++) {
637             // Reset values.
638
//
639
threshold[i] = initThreshold;
640             modulusExceeded[i] = false;
641             eventAlreadyNotified[i] = false;
642             previousScanCounter[i] = null;
643         }
644     }
645
646
647     /**
648      * Returns a <CODE>NotificationInfo</CODE> object containing the
649      * name of the Java class of the notification and the notification
650      * types sent by the counter monitor.
651      */

652     public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
653         String JavaDoc[] types = { MonitorNotification.RUNTIME_ERROR,
654                             MonitorNotification.OBSERVED_OBJECT_ERROR,
655                             MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
656                             MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
657                             MonitorNotification.THRESHOLD_ERROR,
658                             MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
659         MBeanNotificationInfo JavaDoc[] notifsInfo = {
660         new MBeanNotificationInfo JavaDoc(types,
661                       "javax.management.monitor.MonitorNotification",
662                       "Notifications sent by the CounterMonitor MBean")
663     };
664         return notifsInfo;
665     }
666
667     /*
668      * ------------------------------------------
669      * PRIVATE METHODS
670      * ------------------------------------------
671      */

672
673     /**
674      * Updates the derived gauge and the derived gauge timestamp attributes
675      * of the observed object at the specified index.
676      *
677      * @param scanCounter The value of the observed attribute.
678      * @param index The index of the observed object.
679      * @return <CODE>true</CODE> if the derived gauge value is valid,
680      * <CODE>false</CODE> otherwise. The derived gauge value is
681      * invalid when the differenceMode flag is set to
682      * <CODE>true</CODE> and it is the first notification (so we
683      * haven't 2 consecutive values to update the derived gauge).
684      */

685     private synchronized boolean updateDerivedGauge(Object JavaDoc scanCounter,
686                             int index) {
687
688         boolean is_derived_gauge_valid;
689
690         derivedGaugeTimestamp[index] = System.currentTimeMillis();
691
692         // The counter difference mode is used.
693
//
694
if (differenceMode) {
695
696             // The previous scan counter has been initialized.
697
//
698
if (previousScanCounter[index] != null) {
699                 setDerivedGaugeWithDifference((Number JavaDoc)scanCounter, null, index);
700
701                 // If derived gauge is negative it means that the
702
// counter has wrapped around and the value of the
703
// threshold needs to be reset to its initial value.
704
//
705
if (derivedGauge[index].longValue() < 0L) {
706                     if (modulus.longValue() > 0L) {
707                         setDerivedGaugeWithDifference((Number JavaDoc)scanCounter,
708                               (Number JavaDoc)modulus, index);
709                     }
710                     threshold[index] = initThreshold;
711                     eventAlreadyNotified[index] = false;
712                 }
713                 is_derived_gauge_valid = true;
714             }
715             // The previous scan counter has not been initialized.
716
// We cannot update the derived gauge...
717
//
718
else {
719                 is_derived_gauge_valid = false;
720             }
721             previousScanCounter[index] = (Number JavaDoc)scanCounter;
722         }
723         // The counter difference mode is not used.
724
//
725
else {
726             derivedGauge[index] = (Number JavaDoc)scanCounter;
727             is_derived_gauge_valid = true;
728         }
729         return is_derived_gauge_valid;
730     }
731
732     /**
733      * Updates the notification attribute of the observed object at the
734      * specified index and notifies the listeners only once if the notify flag
735      * is set to <CODE>true</CODE>.
736      * @param index The index of the observed object.
737      */

738     private void updateNotifications(int index) {
739     boolean sendNotif = false;
740     String JavaDoc notifType = null;
741     long timeStamp = 0;
742     String JavaDoc msg = null;
743     Object JavaDoc derGauge = null;
744     Object JavaDoc trigger = null;
745
746     synchronized(this) {
747         // Send notification if notify is true.
748
//
749
if (!eventAlreadyNotified[index]) {
750         if (derivedGauge[index].longValue() >=
751             threshold[index].longValue()) {
752             if (notify) {
753             sendNotif = true;
754             notifType = MonitorNotification.THRESHOLD_VALUE_EXCEEDED;
755             timeStamp = derivedGaugeTimestamp[index];
756             msg = "";
757             derGauge = derivedGauge[index];
758             trigger = threshold[index];
759             }
760             if (!differenceMode) {
761             eventAlreadyNotified[index] = true;
762             }
763         }
764         } else {
765         if (isTraceOn()) {
766             trace("updateNotifications", "the notification:" +
767               "\n\tNotification observed object = " +
768               getObservedObject(index) +
769               "\n\tNotification observed attribute = " +
770               getObservedAttribute() +
771               "\n\tNotification derived gauge = " +
772               derivedGauge[index] +
773               "\nhas already been sent");
774         }
775         }
776     }
777
778     if (sendNotif) {
779         sendNotification(notifType, timeStamp, msg, derGauge, trigger, index);
780     }
781     }
782
783     /**
784      * Updates the threshold attribute of the observed object at the
785      * specified index.
786      * @param index The index of the observed object.
787      */

788     private synchronized void updateThreshold(int index) {
789
790         // Calculate the new threshold value if the threshold has been
791
// exceeded and if the offset value is greater than zero.
792
//
793
if (derivedGauge[index].longValue() >= threshold[index].longValue()) {
794
795             if (offset.longValue() > 0L) {
796
797                 // Increment the threshold until its value is greater
798
// than the one for the current derived gauge.
799
//
800
long threshold_value = threshold[index].longValue();
801                 while (derivedGauge[index].longValue() >= threshold_value) {
802                     threshold_value += offset.longValue();
803                 }
804
805                 // Set threshold attribute.
806
//
807
switch(type[index]) {
808                 case INTEGER:
809                     threshold[index] = new Integer JavaDoc((int)threshold_value);
810                     break;
811                 case BYTE:
812                     threshold[index] = new Byte JavaDoc((byte)threshold_value);
813                     break;
814                 case SHORT:
815                     threshold[index] = new Short JavaDoc((short)threshold_value);
816                     break;
817                 case LONG:
818                     threshold[index] = new Long JavaDoc((long)threshold_value);
819                     break;
820                 default:
821                     // Should never occur...
822
if (isDebugOn()) {
823                         debug("updateThreshold", "the threshold type is invalid");
824                     }
825                     break;
826                 }
827
828                 // If the counter can wrap around when it reaches its maximum
829
// and we are not dealing with counter differences then we need
830
// to reset the threshold to its initial value too.
831
//
832
if (!differenceMode) {
833                     if (modulus.longValue() > 0L) {
834                         if (threshold[index].longValue() > modulus.longValue()) {
835                             modulusExceeded[index] = true;
836                             derivedGaugeExceeded[index] = derivedGauge[index];
837                         }
838                     }
839                 }
840
841                 // Threshold value has been modified so we can notify again.
842
//
843
eventAlreadyNotified[index] = false;
844             }
845             else {
846                 modulusExceeded[index] = true;
847                 derivedGaugeExceeded[index] = derivedGauge[index];
848             }
849         }
850     }
851
852     /**
853      * Tests if the threshold, offset and modulus of the specified index are
854      * of the same type as the counter. Only integer types are allowed.
855      *
856      * Note:
857      * If the optional offset or modulus have not been initialized, their
858      * default value is an Integer object with a value equal to zero.
859      *
860      * @param index The index of the observed object.
861      * @return <CODE>true</CODE> if type is the same,
862      * <CODE>false</CODE> otherwise.
863      */

864     private synchronized boolean isThresholdTypeValid(int index) {
865
866     switch(type[index]) {
867     case INTEGER:
868         return ((threshold[index] instanceof Integer JavaDoc) &&
869             ((offset == INTEGER_ZERO) ||
870              (offset instanceof Integer JavaDoc)) &&
871             ((modulus == INTEGER_ZERO) ||
872             (modulus instanceof Integer JavaDoc)));
873     case BYTE:
874         return ((threshold[index] instanceof Byte JavaDoc) &&
875             ((offset == INTEGER_ZERO) ||
876              (offset instanceof Byte JavaDoc)) &&
877             ((modulus == INTEGER_ZERO) ||
878             (modulus instanceof Byte JavaDoc)));
879     case SHORT:
880         return ((threshold[index] instanceof Short JavaDoc) &&
881             ((offset == INTEGER_ZERO) ||
882              (offset instanceof Short JavaDoc)) &&
883             ((modulus == INTEGER_ZERO) ||
884             (modulus instanceof Short JavaDoc)));
885     case LONG:
886         return ((threshold[index] instanceof Long JavaDoc) &&
887             ((offset == INTEGER_ZERO) ||
888              (offset instanceof Long JavaDoc)) &&
889             ((modulus == INTEGER_ZERO) ||
890             (modulus instanceof Long JavaDoc)));
891     default:
892         // Should never occured...
893
if (isDebugOn()) {
894         debug("isThresholdTypeValid", "The threshold type is invalid");
895         }
896         return false;
897     }
898     }
899
900     /**
901      * Sets the derived gauge of the specified index when the
902      * differenceMode flag is set to <CODE>true</CODE>. Integer types
903      * only are allowed.
904      *
905      * @param scanCounter The value of the observed attribute.
906      * @param mod The counter modulus value.
907      * @param index The index of the observed object.
908      */

909     private synchronized void setDerivedGaugeWithDifference(Number JavaDoc scanCounter,
910                                 Number JavaDoc mod,
911                                 int index) {
912     /* We do the arithmetic using longs here even though the
913        result may end up in a smaller type. Since
914        l == (byte)l (mod 256) for any long l,
915        (byte) ((byte)l1 + (byte)l2) == (byte) (l1 + l2),
916        and likewise for subtraction. So it's the same as if
917        we had done the arithmetic in the smaller type.*/

918
919     long derived =
920         scanCounter.longValue() - previousScanCounter[index].longValue();
921     if (mod != null)
922         derived += modulus.longValue();
923
924     switch (type[index]) {
925     case INTEGER: derivedGauge[index] = new Integer JavaDoc((int) derived); break;
926     case BYTE: derivedGauge[index] = new Byte JavaDoc((byte) derived); break;
927     case SHORT: derivedGauge[index] = new Short JavaDoc((short) derived); break;
928     case LONG: derivedGauge[index] = new Long JavaDoc(derived); break;
929     default:
930         // Should never occur...
931
if (isDebugOn()) {
932                 debug("setDerivedGaugeWithDifference",
933               "the threshold type is invalid");
934             }
935         break;
936     }
937     }
938
939     /*
940      * ------------------------------------------
941      * PACKAGE METHODS
942      * ------------------------------------------
943      */

944
945     /**
946      * This method is called by the counter monitor each time
947      * the granularity period has been exceeded.
948      * @param index The index of the observed object.
949      */

950     void notifyAlarmClock(int index) {
951     long timeStamp = 0;
952     String JavaDoc msg = null;
953     Object JavaDoc derGauge = null;
954
955         Object JavaDoc scan_counter = null;
956         String JavaDoc notif_type = null;
957
958     synchronized(this) {
959             if (!isActive())
960         return;
961
962         // Check if the observed object and observed attribute are valid.
963
//
964

965         // Check that neither the observed object nor the
966
// observed attribute are null. If the observed
967
// object or observed attribute is null, this means
968
// that the monitor started before a complete
969
// initialization and nothing is done.
970
//
971
if ((getObservedObject(index) == null) ||
972         (getObservedAttribute() == null)) {
973         return;
974         }
975
976         // Check that the observed object is registered in the
977
// MBean server and that the observed attribute
978
// belongs to the observed object.
979
//
980
try {
981         scan_counter = server.getAttribute(getObservedObject(index),
982                            getObservedAttribute());
983         if (scan_counter == null)
984             return;
985         } catch (NullPointerException JavaDoc np_ex) {
986         if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
987             return;
988         else {
989             notif_type = MonitorNotification.RUNTIME_ERROR;
990             setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
991             msg =
992             "The counter monitor must be registered in " +
993             "the MBean server.";
994         }
995         } catch (InstanceNotFoundException JavaDoc inf_ex) {
996         if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
997             return;
998         else {
999             notif_type = MonitorNotification.OBSERVED_OBJECT_ERROR;
1000            setAlreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED);
1001            msg =
1002            "The observed object must be registered in " +
1003            "the MBean server.";
1004        }
1005        } catch (AttributeNotFoundException JavaDoc anf_ex) {
1006        if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
1007            return;
1008        else {
1009            notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
1010            setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
1011            msg =
1012            "The observed attribute must be accessible in " +
1013            "the observed object.";
1014        }
1015        } catch (MBeanException JavaDoc mb_ex) {
1016        if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1017            return;
1018        else {
1019            notif_type = MonitorNotification.RUNTIME_ERROR;
1020            setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1021            msg = mb_ex.getMessage();
1022        }
1023        } catch (ReflectionException JavaDoc ref_ex) {
1024        if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED)) {
1025            return;
1026        } else {
1027            notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
1028            setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
1029            msg = ref_ex.getMessage();
1030        }
1031        }
1032
1033        if (msg == null) {
1034        // Check that the observed attribute is of type "Integer".
1035
//
1036
if (scan_counter instanceof Integer JavaDoc) {
1037            type[index] = INTEGER;
1038        } else if (scan_counter instanceof Byte JavaDoc) {
1039            type[index] = BYTE;
1040        } else if (scan_counter instanceof Short JavaDoc) {
1041            type[index] = SHORT;
1042        } else if (scan_counter instanceof Long JavaDoc) {
1043            type[index] = LONG;
1044        } else {
1045            if (alreadyNotified(index,
1046                    OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
1047            return;
1048            else {
1049            notif_type =
1050                MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR;
1051            setAlreadyNotified(index,
1052                       OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
1053            msg =
1054                "The observed attribute type must be " +
1055                "an integer type.";
1056            }
1057        }
1058        }
1059
1060        if (msg == null) {
1061        // Check that threshold, offset and modulus have
1062
// values that fit in the counter's type
1063
//
1064
if (!isThresholdTypeValid(index)) {
1065            if (alreadyNotified(index, THRESHOLD_ERROR_NOTIFIED))
1066            return;
1067            else {
1068            notif_type = MonitorNotification.THRESHOLD_ERROR;
1069            setAlreadyNotified(index, THRESHOLD_ERROR_NOTIFIED);
1070            msg =
1071                "The threshold, offset and modulus must " +
1072                "be of the same type as the counter.";
1073            }
1074        }
1075        }
1076
1077        if (msg == null) {
1078
1079        // Clear all already notified flags.
1080
//
1081
resetAllAlreadyNotified(index);
1082
1083        // Check if counter has wrapped around.
1084
//
1085
if (modulusExceeded[index]) {
1086            if (derivedGauge[index].longValue() <
1087            derivedGaugeExceeded[index].longValue()) {
1088            threshold[index] = initThreshold;
1089            modulusExceeded[index] = false;
1090            eventAlreadyNotified[index] = false;
1091            }
1092        }
1093
1094        // Update the derived gauge attributes and check the
1095
// validity of the new value. The derived gauge value
1096
// is invalid when the differenceMode flag is set to
1097
// true and it is the first notification (so we
1098
// haven't 2 consecutive values to update the derived
1099
// gauge).
1100
//
1101
boolean is_derived_gauge_valid =
1102            updateDerivedGauge(scan_counter, index);
1103
1104        // Notify the listeners and update the threshold if
1105
// the updated derived gauge value is valid.
1106
//
1107
if (is_derived_gauge_valid) {
1108            updateNotifications(index);
1109            updateThreshold(index);
1110        }
1111
1112        } else {
1113
1114        // msg != null, will send an error notification
1115

1116        timeStamp = derivedGaugeTimestamp[index];
1117        derGauge = derivedGauge[index];
1118
1119        // Reset values.
1120
//
1121
modulusExceeded[index] = false;
1122        eventAlreadyNotified[index] = false;
1123        previousScanCounter[index] = null;
1124        }
1125    }
1126
1127    if (msg != null) {
1128        sendNotification(notif_type,
1129                 timeStamp,
1130                 msg,
1131                 derGauge,
1132                 null,
1133                 index);
1134    }
1135    }
1136
1137    /**
1138     * This method is called when adding a new observed object in the vector.
1139     * It updates all the counter specific arrays.
1140     * @param index The index of the observed object.
1141     */

1142    synchronized void insertSpecificElementAt(int index) {
1143        // Update threshold, derivedGauge, derivedGaugeTimestamp,
1144
// previousScanCounter, modulusExceeded, derivedGaugeExceeded,
1145
// eventAlreadyNotified and type values.
1146

1147    if (index != elementCount)
1148        throw new Error JavaDoc("Internal error: index != elementCount");
1149
1150    if (elementCount >= threshold.length) {
1151        threshold = expandArray(threshold);
1152        derivedGauge = expandArray(derivedGauge);
1153        previousScanCounter = expandArray(previousScanCounter);
1154        derivedGaugeExceeded = expandArray(derivedGaugeExceeded);
1155        derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
1156        modulusExceeded = expandArray(modulusExceeded);
1157        eventAlreadyNotified = expandArray(eventAlreadyNotified);
1158        type = expandArray(type);
1159    }
1160
1161    threshold[index] = INTEGER_ZERO;
1162    derivedGauge[index] = INTEGER_ZERO;
1163    previousScanCounter[index] = null;
1164    derivedGaugeExceeded[index] = null;
1165    derivedGaugeTimestamp[index] = System.currentTimeMillis();
1166    modulusExceeded[index] = false;
1167    eventAlreadyNotified[index] = false;
1168    type[index] = INTEGER;
1169    }
1170
1171    /**
1172     * This method is called when removing an observed object from the vector.
1173     * It updates all the counter specific arrays.
1174     * @param index The index of the observed object.
1175     */

1176    synchronized void removeSpecificElementAt(int index) {
1177        // Update threshold, derivedGauge, derivedGaugeTimestamp,
1178
// previousScanCounter, modulusExceeded, derivedGaugeExceeded,
1179
// eventAlreadyNotified and type values.
1180
//
1181
removeElementAt(threshold, index);
1182        removeElementAt(derivedGauge, index);
1183        removeElementAt(previousScanCounter, index);
1184        removeElementAt(derivedGaugeExceeded, index);
1185        removeElementAt(derivedGaugeTimestamp, index);
1186        removeElementAt(modulusExceeded, index);
1187        removeElementAt(eventAlreadyNotified, index);
1188        removeElementAt(type, index);
1189    }
1190
1191
1192    /**
1193     * CounterAlarmClock inner class: This class provides a simple
1194     * implementation of an alarm clock MBean. The aim of this MBean is
1195     * to set up an alarm which wakes up the counter monitor every
1196     * granularity period.
1197     */

1198
1199    private static class CounterAlarmClock extends TimerTask JavaDoc {
1200
1201    CounterMonitor JavaDoc listener = null;
1202
1203    /*
1204     * ------------------------------------------
1205     * CONSTRUCTORS
1206     * ------------------------------------------
1207     */

1208
1209    public CounterAlarmClock(CounterMonitor JavaDoc listener) {
1210        this.listener = listener;
1211    }
1212
1213    /*
1214     * ------------------------------------------
1215     * PUBLIC METHODS
1216     * ------------------------------------------
1217     */

1218
1219    /**
1220     * This method is called by the CounterAlarmClock thread when
1221     * it is started.
1222     */

1223    public void run() {
1224        if (listener.isActive()) {
1225        for (int i = 0; i < listener.elementCount; i++) {
1226            listener.notifyAlarmClock(i);
1227        }
1228        }
1229    }
1230    }
1231}
1232
Popular Tags