FileDocCategorySizeDatePackage
CounterMonitor.javaAPI DocJava SE 5 API37465Fri Aug 26 14:57:34 BST 2005javax.management.monitor

CounterMonitor

public class CounterMonitor extends Monitor implements CounterMonitorMBean
Defines a monitor MBean designed to observe the values of a counter attribute.

A counter monitor sends a {@link MonitorNotification#THRESHOLD_VALUE_EXCEEDED threshold notification} when the value of the counter reaches or exceeds a threshold known as the comparison level. The notify flag must be set to true.

In addition, an offset mechanism enables particular counting intervals to be detected. If the offset value is not zero, whenever the threshold is triggered by the counter value reaching a comparison level, that comparison level is incremented by the offset value. This is regarded as taking place instantaneously, that is, before the count is incremented. Thus, for each level, the threshold triggers an event notification every time the count increases by an interval equal to the offset value.

If the counter can wrap around its maximum value, the modulus needs to be specified. The modulus is the value at which the counter is reset to zero.

If the counter difference mode is used, the value of the derived gauge is calculated as the difference between the observed counter values for two successive observations. If this difference is negative, the value of the derived gauge is incremented by the value of the modulus. The derived gauge value (V[t]) is calculated using the following method:

  • if (counter[t] - counter[t-GP]) is positive then V[t] = counter[t] - counter[t-GP]
  • if (counter[t] - counter[t-GP]) is negative then V[t] = counter[t] - counter[t-GP] + MODULUS
This implementation of the counter monitor requires the observed attribute to be of the type integer (Byte, Integer, Short, Long).
version
1.74 05/18/04
author
Sun Microsystems, Inc
since
1.5

Fields Summary
private static final Integer
INTEGER_ZERO
private Number[]
threshold
Counter thresholds.
Each element in this array corresponds to an observed object in the list.
private Number
modulus
Counter modulus.
The default value is a null Integer object.
private Number
offset
Counter offset.
The default value is a null Integer object.
private boolean
notify
Flag indicating if the counter monitor notifies when exceeding the threshold. The default value is set to false.
private boolean
differenceMode
Flag indicating if the counter difference mode is used. If the counter difference mode is used, the derived gauge is the difference between two consecutive observed values. Otherwise, the derived gauge is directly the value of the observed attribute. The default value is set to false.
private Number
initThreshold
Initial counter threshold. This value is used to initialize the threshold when a new object is added to the list and reset the threshold to its initial value each time the counter resets.
private Number[]
derivedGauge
Derived gauges.
Each element in this array corresponds to an observed object in the list.
private long[]
derivedGaugeTimestamp
Derived gauge timestamp.
Each element in this array corresponds to an observed object in the list.
private Number[]
previousScanCounter
Scan counter value captured by the previous observation.
Each element in this array corresponds to an observed object in the list.
private boolean[]
modulusExceeded
Flag indicating if the modulus has been exceeded by the threshold. This flag is used to reset the threshold once we are sure that the counter has been resetted.
Each element in this array corresponds to an observed object in the list.
private Number[]
derivedGaugeExceeded
Derived gauge captured when the modulus has been exceeded by the threshold. This value is used to check if the counter has been resetted (in order to reset the threshold).
Each element in this array corresponds to an observed object in the list.
private boolean[]
eventAlreadyNotified
This flag is used to notify only once between two granularity periods.
Each element in this array corresponds to an observed object in the list.
private int[]
type
This attribute is used to keep the derived gauge type.
Each element in this array corresponds to an observed object in the list.
private static final int
INTEGER
private static final int
BYTE
private static final int
SHORT
private static final int
LONG
private static final int
THRESHOLD_ERROR_NOTIFIED
private Timer
timer
Timer.
Constructors Summary
public CounterMonitor()
Default constructor.

	dbgTag = makeDebugTag();
    
Methods Summary
public synchronized java.lang.NumbergetDerivedGauge()
Returns the derived gauge of the first object in the set of observed MBeans.

return
The derived gauge.
deprecated
As of JMX 1.2, replaced by {@link #getDerivedGauge(ObjectName)}

        return derivedGauge[0];
    
public synchronized java.lang.NumbergetDerivedGauge(javax.management.ObjectName object)
Gets the derived gauge of the specified object, if this object is contained in the set of observed MBeans, or null otherwise.

param
object the name of the object whose derived gauge is to be returned.
return
The derived gauge of the specified object.
since.unbundled
JMX 1.2

	int index = indexOf(object);
	if (index != -1)
	    return derivedGauge[index];
	else
	    return null;
    
public synchronized longgetDerivedGaugeTimeStamp()
Gets the derived gauge timestamp of the first object in the set of observed MBeans.

return
The derived gauge timestamp.
deprecated
As of JMX 1.2, replaced by {@link #getDerivedGaugeTimeStamp(ObjectName)}

        return derivedGaugeTimestamp[0];
    
public synchronized longgetDerivedGaugeTimeStamp(javax.management.ObjectName object)
Gets the derived gauge timestamp of the specified object, if this object is contained in the set of observed MBeans, or null otherwise.

param
object the name of the object whose derived gauge timestamp is to be returned.
return
The derived gauge timestamp of the specified object.
since.unbundled
JMX 1.2

	int index = indexOf(object);
	if (index != -1)
	    return derivedGaugeTimestamp[index];
	else
	    return 0;
    
public synchronized booleangetDifferenceMode()
Gets the difference mode flag value common to all observed MBeans.

return
true if the difference mode is used, false otherwise.
see
#setDifferenceMode

        return differenceMode;
    
public synchronized java.lang.NumbergetInitThreshold()
Gets the initial threshold value common to all observed objects.

return
The initial threshold.
see
#setInitThreshold
since.unbundled
JMX 1.2

        return initThreshold;
    
public synchronized java.lang.NumbergetModulus()
Gets the modulus value common to all observed MBeans.

see
#setModulus
return
The modulus value.

        return modulus;
    
public javax.management.MBeanNotificationInfo[]getNotificationInfo()
Returns a NotificationInfo object containing the name of the Java class of the notification and the notification types sent by the counter monitor.

        String[] types  = { MonitorNotification.RUNTIME_ERROR,
                            MonitorNotification.OBSERVED_OBJECT_ERROR,
                            MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
                            MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
                            MonitorNotification.THRESHOLD_ERROR,
                            MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
        MBeanNotificationInfo[] notifsInfo = {
	    new MBeanNotificationInfo(types,
				      "javax.management.monitor.MonitorNotification",
				      "Notifications sent by the CounterMonitor MBean")
	};
        return notifsInfo;
    
public synchronized booleangetNotify()
Gets the notification's on/off switch value common to all observed MBeans.

return
true if the counter monitor notifies when exceeding the threshold, false otherwise.
see
#setNotify

        return notify;
    
public synchronized java.lang.NumbergetOffset()
Gets the offset value common to all observed MBeans.

return
The offset value.
see
#setOffset

        return offset;
    
public synchronized java.lang.NumbergetThreshold()
Gets the threshold value of the first object in the set of observed MBeans.

return
The threshold value.
see
#setThreshold(Number)
deprecated
As of JMX 1.2, replaced by {@link #getThreshold(ObjectName)}

        return threshold[0];
    
public synchronized java.lang.NumbergetThreshold(javax.management.ObjectName object)
Gets the current threshold value of the specified object, if this object is contained in the set of observed MBeans, or null otherwise.

param
object the name of the object whose threshold is to be returned.
return
The threshold value of the specified object.
see
#setThreshold
since.unbundled
JMX 1.2

	int index = indexOf(object);
	if (index != -1)
	    return threshold[index];
	else
	    return null;
    
synchronized voidinsertSpecificElementAt(int index)
This method is called when adding a new observed object in the vector. It updates all the counter specific arrays.

param
index The index of the observed object.

        // Update threshold, derivedGauge, derivedGaugeTimestamp,
        // previousScanCounter, modulusExceeded, derivedGaugeExceeded,
        // eventAlreadyNotified and type values.

	if (index != elementCount)
	    throw new Error("Internal error: index != elementCount");

	if (elementCount >= threshold.length) {
	    threshold = expandArray(threshold);
	    derivedGauge = expandArray(derivedGauge);
	    previousScanCounter = expandArray(previousScanCounter);
	    derivedGaugeExceeded = expandArray(derivedGaugeExceeded);
	    derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
	    modulusExceeded = expandArray(modulusExceeded);
	    eventAlreadyNotified = expandArray(eventAlreadyNotified);
	    type = expandArray(type);
	}

	threshold[index] = INTEGER_ZERO;
	derivedGauge[index] = INTEGER_ZERO;
	previousScanCounter[index] = null;
	derivedGaugeExceeded[index] = null;
	derivedGaugeTimestamp[index] = System.currentTimeMillis();
	modulusExceeded[index] = false;
	eventAlreadyNotified[index] = false;
	type[index] = INTEGER;
    
private synchronized booleanisThresholdTypeValid(int index)
Tests if the threshold, offset and modulus of the specified index are of the same type as the counter. Only integer types are allowed. Note: If the optional offset or modulus have not been initialized, their default value is an Integer object with a value equal to zero.

param
index The index of the observed object.
return
true if type is the same, false otherwise.


	switch(type[index]) {
	case INTEGER:
	    return ((threshold[index] instanceof Integer) &&
		    ((offset == INTEGER_ZERO) ||
		     (offset instanceof Integer)) &&
		    ((modulus == INTEGER_ZERO) ||
		    (modulus instanceof Integer)));
	case BYTE:
	    return ((threshold[index] instanceof Byte) &&
		    ((offset == INTEGER_ZERO) ||
		     (offset instanceof Byte)) &&
		    ((modulus == INTEGER_ZERO) ||
		    (modulus instanceof Byte)));
	case SHORT:
	    return ((threshold[index] instanceof Short) &&
		    ((offset == INTEGER_ZERO) ||
		     (offset instanceof Short)) &&
		    ((modulus == INTEGER_ZERO) ||
		    (modulus instanceof Short)));
	case LONG:
	    return ((threshold[index] instanceof Long) &&
		    ((offset == INTEGER_ZERO) ||
		     (offset instanceof Long)) &&
		    ((modulus == INTEGER_ZERO) ||
		    (modulus instanceof Long)));
	default:
	    // Should never occured...
	    if (isDebugOn()) {
		debug("isThresholdTypeValid", "The threshold type is invalid");
	    }
	    return false;
	}
    
java.lang.StringmakeDebugTag()



    // TRACES & DEBUG
    //---------------

      
        return "CounterMonitor";
    
voidnotifyAlarmClock(int index)
This method is called by the counter monitor each time the granularity period has been exceeded.

param
index The index of the observed object.

	long timeStamp = 0;
	String msg = null;
	Object derGauge = null;

        Object  scan_counter = null;
        String  notif_type = null;

	synchronized(this) {
            if (!isActive())
		return;

	    // Check if the observed object and observed attribute are valid.
	    //

	    // Check that neither the observed object nor the
	    // observed attribute are null.  If the observed
	    // object or observed attribute is null, this means
	    // that the monitor started before a complete
	    // initialization and nothing is done.
	    //
	    if ((getObservedObject(index) == null) ||
		(getObservedAttribute() == null)) {
		return;
	    }

	    // Check that the observed object is registered in the
	    // MBean server and that the observed attribute
	    // belongs to the observed object.
	    //
	    try {
		scan_counter = server.getAttribute(getObservedObject(index),
						   getObservedAttribute());
		if (scan_counter == null)
		    return;
	    } catch (NullPointerException np_ex) {
		if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
		    return;
		else {
		    notif_type = MonitorNotification.RUNTIME_ERROR;
		    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
		    msg =
			"The counter monitor must be registered in " +
			"the MBean server.";
		}
	    } catch (InstanceNotFoundException inf_ex) {
		if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
		    return;
		else {
		    notif_type = MonitorNotification.OBSERVED_OBJECT_ERROR;
		    setAlreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED);
		    msg =
			"The observed object must be registered in " +
			"the MBean server.";
		}
	    } catch (AttributeNotFoundException anf_ex) {
		if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
		    return;
		else {
		    notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
		    setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
		    msg =
			"The observed attribute must be accessible in " +
			"the observed object.";
		}
	    } catch (MBeanException mb_ex) {
		if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
		    return;
		else {
		    notif_type = MonitorNotification.RUNTIME_ERROR;
		    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
		    msg = mb_ex.getMessage();
		}
	    } catch (ReflectionException ref_ex) {
		if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED)) {
		    return;
		} else {
		    notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
		    setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
		    msg = ref_ex.getMessage();
		}
	    }

	    if (msg == null) {
		// Check that the observed attribute is of type "Integer".
		//
		if (scan_counter instanceof Integer) {
		    type[index] = INTEGER;
		} else if (scan_counter instanceof Byte) {
		    type[index] = BYTE;
		} else if (scan_counter instanceof Short) {
		    type[index] = SHORT;
		} else if (scan_counter instanceof Long) {
		    type[index] = LONG;
		} else {
		    if (alreadyNotified(index,
					OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
			return;
		    else {
			notif_type =
			    MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR;
			setAlreadyNotified(index,
					   OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
			msg =
			    "The observed attribute type must be " +
			    "an integer type.";
		    }
		}
	    }

	    if (msg == null) {
		// Check that threshold, offset and modulus have
		// values that fit in the counter's type
		//
		if (!isThresholdTypeValid(index)) {
		    if (alreadyNotified(index, THRESHOLD_ERROR_NOTIFIED))
			return;
		    else {
			notif_type = MonitorNotification.THRESHOLD_ERROR;
			setAlreadyNotified(index, THRESHOLD_ERROR_NOTIFIED);
			msg =
			    "The threshold, offset and modulus must " +
			    "be of the same type as the counter.";
		    }
		}
	    }

	    if (msg == null) {

		// Clear all already notified flags.
		//
		resetAllAlreadyNotified(index);

		// Check if counter has wrapped around.
		//
		if (modulusExceeded[index]) {
		    if (derivedGauge[index].longValue() <
			derivedGaugeExceeded[index].longValue()) {
			threshold[index] = initThreshold;
			modulusExceeded[index] = false;
			eventAlreadyNotified[index] = false;
		    }
		}

		// Update the derived gauge attributes and check the
		// validity of the new value.  The derived gauge value
		// is invalid when the differenceMode flag is set to
		// true and it is the first notification (so we
		// haven't 2 consecutive values to update the derived
		// gauge).
		//
		boolean is_derived_gauge_valid =
		    updateDerivedGauge(scan_counter, index);

		// Notify the listeners and update the threshold if
		// the updated derived gauge value is valid.
		//
		if (is_derived_gauge_valid) {
		    updateNotifications(index);
		    updateThreshold(index);
		}

	    } else {

		// msg != null, will send an error notification

		timeStamp = derivedGaugeTimestamp[index];
		derGauge = derivedGauge[index];

		// Reset values.
		//
		modulusExceeded[index] = false;
		eventAlreadyNotified[index] = false;
		previousScanCounter[index] = null;
	    }
	}

	if (msg != null) {
	    sendNotification(notif_type,
			     timeStamp,
			     msg,
			     derGauge,
			     null,
			     index);
	}
    
public voidpreDeregister()
Allows the counter monitor MBean to perform any operations it needs before being unregistered by the MBean server.

Resets the threshold values.

exception
java.lang.Exception


        // Stop the CounterMonitor.
        //
        super.preDeregister();

        if (isTraceOn()) {
            trace("preDeregister", "reset the threshold values");
        }

        // Reset values for serialization.
        //
	synchronized (this) {
	    for (int i = 0; i < elementCount; i++) {
		threshold[i] = initThreshold;
	    }
	}
    
synchronized voidremoveSpecificElementAt(int index)
This method is called when removing an observed object from the vector. It updates all the counter specific arrays.

param
index The index of the observed object.

        // Update threshold, derivedGauge, derivedGaugeTimestamp,
        // previousScanCounter, modulusExceeded, derivedGaugeExceeded,
        // eventAlreadyNotified and type values.
        //
        removeElementAt(threshold, index);
        removeElementAt(derivedGauge, index);
        removeElementAt(previousScanCounter, index);
        removeElementAt(derivedGaugeExceeded, index);
        removeElementAt(derivedGaugeTimestamp, index);
        removeElementAt(modulusExceeded, index);
        removeElementAt(eventAlreadyNotified, index);
        removeElementAt(type, index);
    
private synchronized voidsetDerivedGaugeWithDifference(java.lang.Number scanCounter, java.lang.Number mod, int index)
Sets the derived gauge of the specified index when the differenceMode flag is set to true. Integer types only are allowed.

param
scanCounter The value of the observed attribute.
param
mod The counter modulus value.
param
index The index of the observed object.

	/* We do the arithmetic using longs here even though the
	   result may end up in a smaller type.  Since
	   l == (byte)l (mod 256) for any long l,
	   (byte) ((byte)l1 + (byte)l2) == (byte) (l1 + l2),
	   and likewise for subtraction.  So it's the same as if
	   we had done the arithmetic in the smaller type.*/

	long derived =
	    scanCounter.longValue() - previousScanCounter[index].longValue();
	if (mod != null)
	    derived += modulus.longValue();

	switch (type[index]) {
	case INTEGER: derivedGauge[index] = new Integer((int) derived); break;
	case BYTE: derivedGauge[index] = new Byte((byte) derived); break;
	case SHORT: derivedGauge[index] = new Short((short) derived); break;
	case LONG: derivedGauge[index] = new Long(derived); break;
	default:
	    // Should never occur...
            if (isDebugOn()) {
                debug("setDerivedGaugeWithDifference",
		      "the threshold type is invalid");
            }
	    break;
	}
    
public synchronized voidsetDifferenceMode(boolean value)
Sets the difference mode flag value common to all observed MBeans.

param
value The difference mode flag value.
see
#getDifferenceMode

        differenceMode = value;

        for (int i = 0; i < elementCount; i++) {
            // Reset values.
            //
            threshold[i] = initThreshold;
            modulusExceeded[i] = false;
            eventAlreadyNotified[i] = false;
            previousScanCounter[i] = null;
        }
    
public synchronized voidsetGranularityPeriod(long period)
Sets the granularity period (in milliseconds).
The default value of the granularity period is 10 seconds.

param
period The granularity period value.
exception
java.lang.IllegalArgumentException The granularity period is less than or equal to zero.
see
Monitor#setGranularityPeriod(long)

	super.setGranularityPeriod(period);

	// Reschedule timer task if timer is already running
	//
	if (isActive()) {
	    timer.cancel();
	    timer = new Timer();
	    timer.schedule(new CounterAlarmClock(this),
			   getGranularityPeriod(), getGranularityPeriod());
	}
    
public synchronized voidsetInitThreshold(java.lang.Number value)
Sets the initial threshold value common to all observed objects.
The current threshold of every object in the set of observed MBeans is updated consequently.

param
value The initial threshold value.
exception
java.lang.IllegalArgumentException The specified threshold is null or the threshold value is less than zero.
see
#getInitThreshold
since.unbundled
JMX 1.2


        if (value == null) {
            throw new IllegalArgumentException("Null threshold");
        }
        if (value.longValue() < 0L) {
            throw new IllegalArgumentException("Negative threshold");
        }

	initThreshold = value;
	for (int i = 0; i < elementCount; i++) {
	    threshold[i] = value;
	    resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);

            // Reset values.
            //
            modulusExceeded[i] = false;
            eventAlreadyNotified[i] = false;
        }
    
public synchronized voidsetModulus(java.lang.Number value)
Sets the modulus value common to all observed MBeans.

param
value The modulus value.
exception
java.lang.IllegalArgumentException The specified modulus is null or the modulus value is less than zero.
see
#getModulus


        if (value == null) {
            throw new IllegalArgumentException("Null modulus");
        }
        if (value.longValue() < 0L) {
            throw new IllegalArgumentException("Negative modulus");
        }

        modulus = value;
        for (int i = 0; i < elementCount; i++) {
	    resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);

            // Reset values.
            //
            modulusExceeded[i] = false;
        }
    
public synchronized voidsetNotify(boolean value)
Sets the notification's on/off switch value common to all observed MBeans.

param
value The notification's on/off switch value.
see
#getNotify

        notify = value;
    
public synchronized voidsetOffset(java.lang.Number value)
Sets the offset value common to all observed MBeans.

param
value The offset value.
exception
java.lang.IllegalArgumentException The specified offset is null or the offset value is less than zero.
see
#getOffset


        if (value == null) {
            throw new IllegalArgumentException("Null offset");
        }
        if (value.longValue() < 0L) {
            throw new IllegalArgumentException("Negative offset");
        }

	offset = value;
	for (int i = 0; i < elementCount; i++) {
	    resetAlreadyNotified(i, THRESHOLD_ERROR_NOTIFIED);
	}
    
public synchronized voidsetThreshold(java.lang.Number value)
Sets the initial threshold value.

param
value The initial threshold value.
exception
IllegalArgumentException The specified threshold is null or the threshold value is less than zero.
see
#getThreshold()
deprecated
As of JMX 1.2, replaced by {@link #setInitThreshold}

	setInitThreshold(value);
    
public synchronized voidstart()
Starts the counter monitor.

        if (isTraceOn()) {
            trace("start", "start the counter monitor");
        }

	if (isActive()) {
	    if (isTraceOn()) {
		trace("start", "the counter monitor is already activated");
	    }

	    return;
	}

	isActive = true;

	// Reset values.
	//
	for (int i = 0; i < elementCount; i++) {
	    threshold[i] = initThreshold;
	    modulusExceeded[i] = false;
	    eventAlreadyNotified[i] = false;
	    previousScanCounter[i] = null;
	}

	// Start the timer.
	//
	timer = new Timer();
	timer.schedule(new CounterAlarmClock(this), getGranularityPeriod(),
		       getGranularityPeriod());
    
public synchronized voidstop()
Stops the counter monitor. This method is not synchronized, because if it were there could be a deadlock with a thread that attempted to get the lock on the monitor before being interrupted or noticing that it had been interrupted.

        if (isTraceOn()) {
            trace("stop", "stop the counter monitor");
        }

	if (isTraceOn()) {
	    trace("stop", "the counter monitor is not started");

	    return;
	}

	isActive = false;

	// Stop the timer.
	//
	if (timer != null) {
	    timer.cancel();
	    timer = null;
	}
    
private synchronized booleanupdateDerivedGauge(java.lang.Object scanCounter, int index)
Updates the derived gauge and the derived gauge timestamp attributes of the observed object at the specified index.

param
scanCounter The value of the observed attribute.
param
index The index of the observed object.
return
true if the derived gauge value is valid, false otherwise. The derived gauge value is invalid when the differenceMode flag is set to true and it is the first notification (so we haven't 2 consecutive values to update the derived gauge).


        boolean is_derived_gauge_valid;

        derivedGaugeTimestamp[index] = System.currentTimeMillis();

        // The counter difference mode is used.
        //
        if (differenceMode) {

            // The previous scan counter has been initialized.
            //
            if (previousScanCounter[index] != null) {
                setDerivedGaugeWithDifference((Number)scanCounter, null, index);

                // If derived gauge is negative it means that the
                // counter has wrapped around and the value of the
                // threshold needs to be reset to its initial value.
                //
                if (derivedGauge[index].longValue() < 0L) {
                    if (modulus.longValue() > 0L) {
                        setDerivedGaugeWithDifference((Number)scanCounter,
						      (Number)modulus, index);
                    }
                    threshold[index] = initThreshold;
                    eventAlreadyNotified[index] = false;
                }
                is_derived_gauge_valid = true;
            }
            // The previous scan counter has not been initialized.
            // We cannot update the derived gauge...
            //
            else {
                is_derived_gauge_valid = false;
            }
            previousScanCounter[index] = (Number)scanCounter;
        }
        // The counter difference mode is not used.
        //
        else {
            derivedGauge[index] = (Number)scanCounter;
            is_derived_gauge_valid = true;
        }
        return is_derived_gauge_valid;
    
private voidupdateNotifications(int index)
Updates the notification attribute of the observed object at the specified index and notifies the listeners only once if the notify flag is set to true.

param
index The index of the observed object.

	boolean sendNotif = false;
	String notifType = null;
	long timeStamp = 0;
	String msg = null;
	Object derGauge = null;
	Object trigger = null;

	synchronized(this) {
	    // Send notification if notify is true.
	    //
	    if (!eventAlreadyNotified[index]) {
		if (derivedGauge[index].longValue() >=
		    threshold[index].longValue()) {
		    if (notify) {
			sendNotif = true;
			notifType = MonitorNotification.THRESHOLD_VALUE_EXCEEDED;
			timeStamp = derivedGaugeTimestamp[index];
			msg = "";
			derGauge = derivedGauge[index];
			trigger = threshold[index];
		    }
		    if (!differenceMode) {
			eventAlreadyNotified[index] = true;
		    }
		}
	    } else {
		if (isTraceOn()) {
		    trace("updateNotifications", "the notification:" +
			  "\n\tNotification observed object = " +
			  getObservedObject(index) +
			  "\n\tNotification observed attribute = " +
			  getObservedAttribute() +
			  "\n\tNotification derived gauge = " +
			  derivedGauge[index] +
			  "\nhas already been sent");
		}
	    }
	}

	if (sendNotif) {
	    sendNotification(notifType, timeStamp, msg, derGauge, trigger, index);
	}
    
private synchronized voidupdateThreshold(int index)
Updates the threshold attribute of the observed object at the specified index.

param
index The index of the observed object.


        // Calculate the new threshold value if the threshold has been
        // exceeded and if the offset value is greater than zero.
        //
        if (derivedGauge[index].longValue() >=  threshold[index].longValue()) {

            if (offset.longValue() > 0L) {

                // Increment the threshold until its value is greater
                // than the one for the current derived gauge.
                //
                long threshold_value = threshold[index].longValue();
                while (derivedGauge[index].longValue() >= threshold_value) {
                    threshold_value += offset.longValue();
                }

                // Set threshold attribute.
                //
                switch(type[index]) {
                case INTEGER:
                    threshold[index] = new Integer((int)threshold_value);
                    break;
                case BYTE:
                    threshold[index] = new Byte((byte)threshold_value);
                    break;
                case SHORT:
                    threshold[index] = new Short((short)threshold_value);
                    break;
                case LONG:
                    threshold[index] = new Long((long)threshold_value);
                    break;
                default:
                    // Should never occur...
                    if (isDebugOn()) {
                        debug("updateThreshold", "the threshold type is invalid");
                    }
                    break;
                }

                // If the counter can wrap around when it reaches its maximum
                // and we are not dealing with counter differences then we need
                // to reset the threshold to its initial value too.
                //
                if (!differenceMode) {
                    if (modulus.longValue() > 0L) {
                        if (threshold[index].longValue() > modulus.longValue()) {
                            modulusExceeded[index] = true;
                            derivedGaugeExceeded[index] = derivedGauge[index];
                        }
                    }
                }

                // Threshold value has been modified so we can notify again.
                //
                eventAlreadyNotified[index] = false;
            }
            else {
                modulusExceeded[index] = true;
                derivedGaugeExceeded[index] = derivedGauge[index];
            }
        }