You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
982 lines
32 KiB
982 lines
32 KiB
/*
|
|
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
package javax.management.monitor;
|
|
|
|
import static com.sun.jmx.defaults.JmxProperties.MONITOR_LOGGER;
|
|
import java.util.logging.Level;
|
|
import javax.management.ObjectName;
|
|
import javax.management.MBeanNotificationInfo;
|
|
import static javax.management.monitor.Monitor.NumericalType.*;
|
|
import static javax.management.monitor.MonitorNotification.*;
|
|
|
|
/**
|
|
* Defines a monitor MBean designed to observe the values of a counter
|
|
* attribute.
|
|
*
|
|
* <P> 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 <CODE>true</CODE>.
|
|
*
|
|
* <P> 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.
|
|
*
|
|
* <P> 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.
|
|
*
|
|
* <P> 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:
|
|
*
|
|
* <UL>
|
|
* <LI>if (counter[t] - counter[t-GP]) is positive then
|
|
* V[t] = counter[t] - counter[t-GP]
|
|
* <LI>if (counter[t] - counter[t-GP]) is negative then
|
|
* V[t] = counter[t] - counter[t-GP] + MODULUS
|
|
* </UL>
|
|
*
|
|
* This implementation of the counter monitor requires the observed
|
|
* attribute to be of the type integer (<CODE>Byte</CODE>,
|
|
* <CODE>Integer</CODE>, <CODE>Short</CODE>, <CODE>Long</CODE>).
|
|
*
|
|
*
|
|
* @since 1.5
|
|
*/
|
|
public class CounterMonitor extends Monitor implements CounterMonitorMBean {
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* PACKAGE CLASSES
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
static class CounterMonitorObservedObject extends ObservedObject {
|
|
|
|
public CounterMonitorObservedObject(ObjectName observedObject) {
|
|
super(observedObject);
|
|
}
|
|
|
|
public final synchronized Number getThreshold() {
|
|
return threshold;
|
|
}
|
|
public final synchronized void setThreshold(Number threshold) {
|
|
this.threshold = threshold;
|
|
}
|
|
public final synchronized Number getPreviousScanCounter() {
|
|
return previousScanCounter;
|
|
}
|
|
public final synchronized void setPreviousScanCounter(
|
|
Number previousScanCounter) {
|
|
this.previousScanCounter = previousScanCounter;
|
|
}
|
|
public final synchronized boolean getModulusExceeded() {
|
|
return modulusExceeded;
|
|
}
|
|
public final synchronized void setModulusExceeded(
|
|
boolean modulusExceeded) {
|
|
this.modulusExceeded = modulusExceeded;
|
|
}
|
|
public final synchronized Number getDerivedGaugeExceeded() {
|
|
return derivedGaugeExceeded;
|
|
}
|
|
public final synchronized void setDerivedGaugeExceeded(
|
|
Number derivedGaugeExceeded) {
|
|
this.derivedGaugeExceeded = derivedGaugeExceeded;
|
|
}
|
|
public final synchronized boolean getDerivedGaugeValid() {
|
|
return derivedGaugeValid;
|
|
}
|
|
public final synchronized void setDerivedGaugeValid(
|
|
boolean derivedGaugeValid) {
|
|
this.derivedGaugeValid = derivedGaugeValid;
|
|
}
|
|
public final synchronized boolean getEventAlreadyNotified() {
|
|
return eventAlreadyNotified;
|
|
}
|
|
public final synchronized void setEventAlreadyNotified(
|
|
boolean eventAlreadyNotified) {
|
|
this.eventAlreadyNotified = eventAlreadyNotified;
|
|
}
|
|
public final synchronized NumericalType getType() {
|
|
return type;
|
|
}
|
|
public final synchronized void setType(NumericalType type) {
|
|
this.type = type;
|
|
}
|
|
|
|
private Number threshold;
|
|
private Number previousScanCounter;
|
|
private boolean modulusExceeded;
|
|
private Number derivedGaugeExceeded;
|
|
private boolean derivedGaugeValid;
|
|
private boolean eventAlreadyNotified;
|
|
private NumericalType type;
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* PRIVATE VARIABLES
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Counter modulus.
|
|
* <BR>The default value is a null Integer object.
|
|
*/
|
|
private Number modulus = INTEGER_ZERO;
|
|
|
|
/**
|
|
* Counter offset.
|
|
* <BR>The default value is a null Integer object.
|
|
*/
|
|
private Number offset = INTEGER_ZERO;
|
|
|
|
/**
|
|
* Flag indicating if the counter monitor notifies when exceeding
|
|
* the threshold. The default value is set to
|
|
* <CODE>false</CODE>.
|
|
*/
|
|
private boolean notify = false;
|
|
|
|
/**
|
|
* 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 <CODE>false</CODE>.
|
|
*/
|
|
private boolean differenceMode = false;
|
|
|
|
/**
|
|
* 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 initThreshold = INTEGER_ZERO;
|
|
|
|
private static final String[] types = {
|
|
RUNTIME_ERROR,
|
|
OBSERVED_OBJECT_ERROR,
|
|
OBSERVED_ATTRIBUTE_ERROR,
|
|
OBSERVED_ATTRIBUTE_TYPE_ERROR,
|
|
THRESHOLD_ERROR,
|
|
THRESHOLD_VALUE_EXCEEDED
|
|
};
|
|
|
|
private static final MBeanNotificationInfo[] notifsInfo = {
|
|
new MBeanNotificationInfo(
|
|
types,
|
|
"javax.management.monitor.MonitorNotification",
|
|
"Notifications sent by the CounterMonitor MBean")
|
|
};
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* CONSTRUCTORS
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
public CounterMonitor() {
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* PUBLIC METHODS
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Starts the counter monitor.
|
|
*/
|
|
public synchronized void start() {
|
|
if (isActive()) {
|
|
MONITOR_LOGGER.logp(Level.FINER, CounterMonitor.class.getName(),
|
|
"start", "the monitor is already active");
|
|
return;
|
|
}
|
|
// Reset values.
|
|
//
|
|
for (ObservedObject o : observedObjects) {
|
|
final CounterMonitorObservedObject cmo =
|
|
(CounterMonitorObservedObject) o;
|
|
cmo.setThreshold(initThreshold);
|
|
cmo.setModulusExceeded(false);
|
|
cmo.setEventAlreadyNotified(false);
|
|
cmo.setPreviousScanCounter(null);
|
|
}
|
|
doStart();
|
|
}
|
|
|
|
/**
|
|
* Stops the counter monitor.
|
|
*/
|
|
public synchronized void stop() {
|
|
doStop();
|
|
}
|
|
|
|
// GETTERS AND SETTERS
|
|
//--------------------
|
|
|
|
/**
|
|
* Gets the derived gauge of the specified object, if this object is
|
|
* contained in the set of observed MBeans, or <code>null</code> otherwise.
|
|
*
|
|
* @param object the name of the object whose derived gauge is to
|
|
* be returned.
|
|
*
|
|
* @return The derived gauge of the specified object.
|
|
*
|
|
*/
|
|
@Override
|
|
public synchronized Number getDerivedGauge(ObjectName object) {
|
|
return (Number) super.getDerivedGauge(object);
|
|
}
|
|
|
|
/**
|
|
* Gets the derived gauge timestamp of the specified object, if
|
|
* this object is contained in the set of observed MBeans, or
|
|
* <code>0</code> 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.
|
|
*
|
|
*/
|
|
@Override
|
|
public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
|
|
return super.getDerivedGaugeTimeStamp(object);
|
|
}
|
|
|
|
/**
|
|
* Gets the current threshold value of the specified object, if
|
|
* this object is contained in the set of observed MBeans, or
|
|
* <code>null</code> otherwise.
|
|
*
|
|
* @param object the name of the object whose threshold is to be
|
|
* returned.
|
|
*
|
|
* @return The threshold value of the specified object.
|
|
*
|
|
*/
|
|
public synchronized Number getThreshold(ObjectName object) {
|
|
final CounterMonitorObservedObject o =
|
|
(CounterMonitorObservedObject) getObservedObject(object);
|
|
if (o == null)
|
|
return null;
|
|
|
|
// If the counter that is monitored rolls over when it reaches a
|
|
// maximum value, then the modulus value needs to be set to that
|
|
// maximum value. The threshold will then also roll over whenever
|
|
// it strictly exceeds the modulus value. When the threshold rolls
|
|
// over, it is reset to the value that was specified through the
|
|
// latest call to the monitor's setInitThreshold method, before
|
|
// any offsets were applied.
|
|
//
|
|
if (offset.longValue() > 0L &&
|
|
modulus.longValue() > 0L &&
|
|
o.getThreshold().longValue() > modulus.longValue()) {
|
|
return initThreshold;
|
|
} else {
|
|
return o.getThreshold();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the initial threshold value common to all observed objects.
|
|
*
|
|
* @return The initial threshold.
|
|
*
|
|
* @see #setInitThreshold
|
|
*
|
|
*/
|
|
public synchronized Number getInitThreshold() {
|
|
return initThreshold;
|
|
}
|
|
|
|
/**
|
|
* Sets the initial threshold value common to all observed objects.
|
|
*
|
|
* <BR>The current threshold of every object in the set of
|
|
* observed MBeans is updated consequently.
|
|
*
|
|
* @param value The initial threshold value.
|
|
*
|
|
* @exception IllegalArgumentException The specified
|
|
* threshold is null or the threshold value is less than zero.
|
|
*
|
|
* @see #getInitThreshold
|
|
*
|
|
*/
|
|
public synchronized void setInitThreshold(Number value)
|
|
throws IllegalArgumentException {
|
|
|
|
if (value == null) {
|
|
throw new IllegalArgumentException("Null threshold");
|
|
}
|
|
if (value.longValue() < 0L) {
|
|
throw new IllegalArgumentException("Negative threshold");
|
|
}
|
|
|
|
if (initThreshold.equals(value))
|
|
return;
|
|
initThreshold = value;
|
|
|
|
// Reset values.
|
|
//
|
|
int index = 0;
|
|
for (ObservedObject o : observedObjects) {
|
|
resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
|
|
final CounterMonitorObservedObject cmo =
|
|
(CounterMonitorObservedObject) o;
|
|
cmo.setThreshold(value);
|
|
cmo.setModulusExceeded(false);
|
|
cmo.setEventAlreadyNotified(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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)}
|
|
*/
|
|
@Deprecated
|
|
public synchronized Number getDerivedGauge() {
|
|
if (observedObjects.isEmpty()) {
|
|
return null;
|
|
} else {
|
|
return (Number) observedObjects.get(0).getDerivedGauge();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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)}
|
|
*/
|
|
@Deprecated
|
|
public synchronized long getDerivedGaugeTimeStamp() {
|
|
if (observedObjects.isEmpty()) {
|
|
return 0;
|
|
} else {
|
|
return observedObjects.get(0).getDerivedGaugeTimeStamp();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the threshold value of the first object in the set of
|
|
* observed MBeans.
|
|
*
|
|
* @return The threshold value.
|
|
*
|
|
* @see #setThreshold
|
|
*
|
|
* @deprecated As of JMX 1.2, replaced by {@link #getThreshold(ObjectName)}
|
|
*/
|
|
@Deprecated
|
|
public synchronized Number getThreshold() {
|
|
return getThreshold(getObservedObject());
|
|
}
|
|
|
|
/**
|
|
* 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}
|
|
*/
|
|
@Deprecated
|
|
public synchronized void setThreshold(Number value)
|
|
throws IllegalArgumentException {
|
|
setInitThreshold(value);
|
|
}
|
|
|
|
/**
|
|
* Gets the offset value common to all observed MBeans.
|
|
*
|
|
* @return The offset value.
|
|
*
|
|
* @see #setOffset
|
|
*/
|
|
public synchronized Number getOffset() {
|
|
return offset;
|
|
}
|
|
|
|
/**
|
|
* Sets the offset value common to all observed MBeans.
|
|
*
|
|
* @param value The offset value.
|
|
*
|
|
* @exception IllegalArgumentException The specified
|
|
* offset is null or the offset value is less than zero.
|
|
*
|
|
* @see #getOffset
|
|
*/
|
|
public synchronized void setOffset(Number value)
|
|
throws IllegalArgumentException {
|
|
|
|
if (value == null) {
|
|
throw new IllegalArgumentException("Null offset");
|
|
}
|
|
if (value.longValue() < 0L) {
|
|
throw new IllegalArgumentException("Negative offset");
|
|
}
|
|
|
|
if (offset.equals(value))
|
|
return;
|
|
offset = value;
|
|
|
|
int index = 0;
|
|
for (ObservedObject o : observedObjects) {
|
|
resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the modulus value common to all observed MBeans.
|
|
*
|
|
* @see #setModulus
|
|
*
|
|
* @return The modulus value.
|
|
*/
|
|
public synchronized Number getModulus() {
|
|
return modulus;
|
|
}
|
|
|
|
/**
|
|
* Sets the modulus value common to all observed MBeans.
|
|
*
|
|
* @param value The modulus value.
|
|
*
|
|
* @exception IllegalArgumentException The specified
|
|
* modulus is null or the modulus value is less than zero.
|
|
*
|
|
* @see #getModulus
|
|
*/
|
|
public synchronized void setModulus(Number value)
|
|
throws IllegalArgumentException {
|
|
|
|
if (value == null) {
|
|
throw new IllegalArgumentException("Null modulus");
|
|
}
|
|
if (value.longValue() < 0L) {
|
|
throw new IllegalArgumentException("Negative modulus");
|
|
}
|
|
|
|
if (modulus.equals(value))
|
|
return;
|
|
modulus = value;
|
|
|
|
// Reset values.
|
|
//
|
|
int index = 0;
|
|
for (ObservedObject o : observedObjects) {
|
|
resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
|
|
final CounterMonitorObservedObject cmo =
|
|
(CounterMonitorObservedObject) o;
|
|
cmo.setModulusExceeded(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the notification's on/off switch value common to all
|
|
* observed MBeans.
|
|
*
|
|
* @return <CODE>true</CODE> if the counter monitor notifies when
|
|
* exceeding the threshold, <CODE>false</CODE> otherwise.
|
|
*
|
|
* @see #setNotify
|
|
*/
|
|
public synchronized boolean getNotify() {
|
|
return notify;
|
|
}
|
|
|
|
/**
|
|
* Sets the notification's on/off switch value common to all
|
|
* observed MBeans.
|
|
*
|
|
* @param value The notification's on/off switch value.
|
|
*
|
|
* @see #getNotify
|
|
*/
|
|
public synchronized void setNotify(boolean value) {
|
|
if (notify == value)
|
|
return;
|
|
notify = value;
|
|
}
|
|
|
|
/**
|
|
* Gets the difference mode flag value common to all observed MBeans.
|
|
*
|
|
* @return <CODE>true</CODE> if the difference mode is used,
|
|
* <CODE>false</CODE> otherwise.
|
|
*
|
|
* @see #setDifferenceMode
|
|
*/
|
|
public synchronized boolean getDifferenceMode() {
|
|
return differenceMode;
|
|
}
|
|
|
|
/**
|
|
* Sets the difference mode flag value common to all observed MBeans.
|
|
*
|
|
* @param value The difference mode flag value.
|
|
*
|
|
* @see #getDifferenceMode
|
|
*/
|
|
public synchronized void setDifferenceMode(boolean value) {
|
|
if (differenceMode == value)
|
|
return;
|
|
differenceMode = value;
|
|
|
|
// Reset values.
|
|
//
|
|
for (ObservedObject o : observedObjects) {
|
|
final CounterMonitorObservedObject cmo =
|
|
(CounterMonitorObservedObject) o;
|
|
cmo.setThreshold(initThreshold);
|
|
cmo.setModulusExceeded(false);
|
|
cmo.setEventAlreadyNotified(false);
|
|
cmo.setPreviousScanCounter(null);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a <CODE>NotificationInfo</CODE> object containing the
|
|
* name of the Java class of the notification and the notification
|
|
* types sent by the counter monitor.
|
|
*/
|
|
@Override
|
|
public MBeanNotificationInfo[] getNotificationInfo() {
|
|
return notifsInfo.clone();
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* PRIVATE METHODS
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Updates the derived gauge attribute of the observed object.
|
|
*
|
|
* @param scanCounter The value of the observed attribute.
|
|
* @param o The observed object.
|
|
* @return <CODE>true</CODE> if the derived gauge value is valid,
|
|
* <CODE>false</CODE> otherwise. The derived gauge value is
|
|
* invalid when the differenceMode flag is set to
|
|
* <CODE>true</CODE> and it is the first notification (so we
|
|
* haven't 2 consecutive values to update the derived gauge).
|
|
*/
|
|
private synchronized boolean updateDerivedGauge(
|
|
Object scanCounter, CounterMonitorObservedObject o) {
|
|
|
|
boolean is_derived_gauge_valid;
|
|
|
|
// The counter difference mode is used.
|
|
//
|
|
if (differenceMode) {
|
|
|
|
// The previous scan counter has been initialized.
|
|
//
|
|
if (o.getPreviousScanCounter() != null) {
|
|
setDerivedGaugeWithDifference((Number)scanCounter, null, o);
|
|
|
|
// 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 (((Number)o.getDerivedGauge()).longValue() < 0L) {
|
|
if (modulus.longValue() > 0L) {
|
|
setDerivedGaugeWithDifference((Number)scanCounter,
|
|
modulus, o);
|
|
}
|
|
o.setThreshold(initThreshold);
|
|
o.setEventAlreadyNotified(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;
|
|
}
|
|
o.setPreviousScanCounter((Number)scanCounter);
|
|
}
|
|
// The counter difference mode is not used.
|
|
//
|
|
else {
|
|
o.setDerivedGauge((Number)scanCounter);
|
|
is_derived_gauge_valid = true;
|
|
}
|
|
return is_derived_gauge_valid;
|
|
}
|
|
|
|
/**
|
|
* Updates the notification attribute of the observed object
|
|
* and notifies the listeners only once if the notify flag
|
|
* is set to <CODE>true</CODE>.
|
|
* @param o The observed object.
|
|
*/
|
|
private synchronized MonitorNotification updateNotifications(
|
|
CounterMonitorObservedObject o) {
|
|
|
|
MonitorNotification n = null;
|
|
|
|
// Send notification if notify is true.
|
|
//
|
|
if (!o.getEventAlreadyNotified()) {
|
|
if (((Number)o.getDerivedGauge()).longValue() >=
|
|
o.getThreshold().longValue()) {
|
|
if (notify) {
|
|
n = new MonitorNotification(THRESHOLD_VALUE_EXCEEDED,
|
|
this,
|
|
0,
|
|
0,
|
|
"",
|
|
null,
|
|
null,
|
|
null,
|
|
o.getThreshold());
|
|
}
|
|
if (!differenceMode) {
|
|
o.setEventAlreadyNotified(true);
|
|
}
|
|
}
|
|
} else {
|
|
if (MONITOR_LOGGER.isLoggable(Level.FINER)) {
|
|
final StringBuilder strb = new StringBuilder()
|
|
.append("The notification:")
|
|
.append("\n\tNotification observed object = ")
|
|
.append(o.getObservedObject())
|
|
.append("\n\tNotification observed attribute = ")
|
|
.append(getObservedAttribute())
|
|
.append("\n\tNotification threshold level = ")
|
|
.append(o.getThreshold())
|
|
.append("\n\tNotification derived gauge = ")
|
|
.append(o.getDerivedGauge())
|
|
.append("\nhas already been sent");
|
|
MONITOR_LOGGER.logp(Level.FINER, CounterMonitor.class.getName(),
|
|
"updateNotifications", strb.toString());
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
/**
|
|
* Updates the threshold attribute of the observed object.
|
|
* @param o The observed object.
|
|
*/
|
|
private synchronized void updateThreshold(CounterMonitorObservedObject o) {
|
|
|
|
// Calculate the new threshold value if the threshold has been
|
|
// exceeded and if the offset value is greater than zero.
|
|
//
|
|
if (((Number)o.getDerivedGauge()).longValue() >=
|
|
o.getThreshold().longValue()) {
|
|
|
|
if (offset.longValue() > 0L) {
|
|
|
|
// Increment the threshold until its value is greater
|
|
// than the one for the current derived gauge.
|
|
//
|
|
long threshold_value = o.getThreshold().longValue();
|
|
while (((Number)o.getDerivedGauge()).longValue() >=
|
|
threshold_value) {
|
|
threshold_value += offset.longValue();
|
|
}
|
|
|
|
// Set threshold attribute.
|
|
//
|
|
switch (o.getType()) {
|
|
case INTEGER:
|
|
o.setThreshold(Integer.valueOf((int)threshold_value));
|
|
break;
|
|
case BYTE:
|
|
o.setThreshold(Byte.valueOf((byte)threshold_value));
|
|
break;
|
|
case SHORT:
|
|
o.setThreshold(Short.valueOf((short)threshold_value));
|
|
break;
|
|
case LONG:
|
|
o.setThreshold(Long.valueOf(threshold_value));
|
|
break;
|
|
default:
|
|
// Should never occur...
|
|
MONITOR_LOGGER.logp(Level.FINEST,
|
|
CounterMonitor.class.getName(),
|
|
"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 (o.getThreshold().longValue() >
|
|
modulus.longValue()) {
|
|
o.setModulusExceeded(true);
|
|
o.setDerivedGaugeExceeded(
|
|
(Number) o.getDerivedGauge());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Threshold value has been modified so we can notify again.
|
|
//
|
|
o.setEventAlreadyNotified(false);
|
|
} else {
|
|
o.setModulusExceeded(true);
|
|
o.setDerivedGaugeExceeded((Number) o.getDerivedGauge());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the derived gauge of the specified observed object when the
|
|
* differenceMode flag is set to <CODE>true</CODE>. Integer types
|
|
* only are allowed.
|
|
*
|
|
* @param scanCounter The value of the observed attribute.
|
|
* @param mod The counter modulus value.
|
|
* @param o The observed object.
|
|
*/
|
|
private synchronized void setDerivedGaugeWithDifference(
|
|
Number scanCounter, Number mod, CounterMonitorObservedObject o) {
|
|
/* 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() - o.getPreviousScanCounter().longValue();
|
|
if (mod != null)
|
|
derived += modulus.longValue();
|
|
|
|
switch (o.getType()) {
|
|
case INTEGER: o.setDerivedGauge(Integer.valueOf((int) derived)); break;
|
|
case BYTE: o.setDerivedGauge(Byte.valueOf((byte) derived)); break;
|
|
case SHORT: o.setDerivedGauge(Short.valueOf((short) derived)); break;
|
|
case LONG: o.setDerivedGauge(Long.valueOf(derived)); break;
|
|
default:
|
|
// Should never occur...
|
|
MONITOR_LOGGER.logp(Level.FINEST, CounterMonitor.class.getName(),
|
|
"setDerivedGaugeWithDifference",
|
|
"the threshold type is invalid");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ------------------------------------------
|
|
* PACKAGE METHODS
|
|
* ------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Factory method for ObservedObject creation.
|
|
*
|
|
* @since 1.6
|
|
*/
|
|
@Override
|
|
ObservedObject createObservedObject(ObjectName object) {
|
|
final CounterMonitorObservedObject cmo =
|
|
new CounterMonitorObservedObject(object);
|
|
cmo.setThreshold(initThreshold);
|
|
cmo.setModulusExceeded(false);
|
|
cmo.setEventAlreadyNotified(false);
|
|
cmo.setPreviousScanCounter(null);
|
|
return cmo;
|
|
}
|
|
|
|
/**
|
|
* This method globally sets the derived gauge type for the given
|
|
* "object" and "attribute" after checking that the type of the
|
|
* supplied observed attribute value is one of the value types
|
|
* supported by this monitor.
|
|
*/
|
|
@Override
|
|
synchronized boolean isComparableTypeValid(ObjectName object,
|
|
String attribute,
|
|
Comparable<?> value) {
|
|
final CounterMonitorObservedObject o =
|
|
(CounterMonitorObservedObject) getObservedObject(object);
|
|
if (o == null)
|
|
return false;
|
|
|
|
// Check that the observed attribute is of type "Integer".
|
|
//
|
|
if (value instanceof Integer) {
|
|
o.setType(INTEGER);
|
|
} else if (value instanceof Byte) {
|
|
o.setType(BYTE);
|
|
} else if (value instanceof Short) {
|
|
o.setType(SHORT);
|
|
} else if (value instanceof Long) {
|
|
o.setType(LONG);
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
synchronized Comparable<?> getDerivedGaugeFromComparable(
|
|
ObjectName object,
|
|
String attribute,
|
|
Comparable<?> value) {
|
|
final CounterMonitorObservedObject o =
|
|
(CounterMonitorObservedObject) getObservedObject(object);
|
|
if (o == null)
|
|
return null;
|
|
|
|
// Check if counter has wrapped around.
|
|
//
|
|
if (o.getModulusExceeded()) {
|
|
if (((Number)o.getDerivedGauge()).longValue() <
|
|
o.getDerivedGaugeExceeded().longValue()) {
|
|
o.setThreshold(initThreshold);
|
|
o.setModulusExceeded(false);
|
|
o.setEventAlreadyNotified(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, i.e. we
|
|
// haven't got 2 consecutive values to update the
|
|
// derived gauge.
|
|
//
|
|
o.setDerivedGaugeValid(updateDerivedGauge(value, o));
|
|
|
|
return (Comparable<?>) o.getDerivedGauge();
|
|
}
|
|
|
|
@Override
|
|
synchronized void onErrorNotification(MonitorNotification notification) {
|
|
final CounterMonitorObservedObject o = (CounterMonitorObservedObject)
|
|
getObservedObject(notification.getObservedObject());
|
|
if (o == null)
|
|
return;
|
|
|
|
// Reset values.
|
|
//
|
|
o.setModulusExceeded(false);
|
|
o.setEventAlreadyNotified(false);
|
|
o.setPreviousScanCounter(null);
|
|
}
|
|
|
|
@Override
|
|
synchronized MonitorNotification buildAlarmNotification(
|
|
ObjectName object,
|
|
String attribute,
|
|
Comparable<?> value) {
|
|
final CounterMonitorObservedObject o =
|
|
(CounterMonitorObservedObject) getObservedObject(object);
|
|
if (o == null)
|
|
return null;
|
|
|
|
// Notify the listeners and update the threshold if
|
|
// the updated derived gauge value is valid.
|
|
//
|
|
final MonitorNotification alarm;
|
|
if (o.getDerivedGaugeValid()) {
|
|
alarm = updateNotifications(o);
|
|
updateThreshold(o);
|
|
} else {
|
|
alarm = null;
|
|
}
|
|
return alarm;
|
|
}
|
|
|
|
/**
|
|
* Tests if the threshold, offset and modulus of the specified observed
|
|
* object 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 object The observed object.
|
|
* @param attribute The observed attribute.
|
|
* @param value The sample value.
|
|
* @return <CODE>true</CODE> if type is the same,
|
|
* <CODE>false</CODE> otherwise.
|
|
*/
|
|
@Override
|
|
synchronized boolean isThresholdTypeValid(ObjectName object,
|
|
String attribute,
|
|
Comparable<?> value) {
|
|
final CounterMonitorObservedObject o =
|
|
(CounterMonitorObservedObject) getObservedObject(object);
|
|
if (o == null)
|
|
return false;
|
|
|
|
Class<? extends Number> c = classForType(o.getType());
|
|
return (c.isInstance(o.getThreshold()) &&
|
|
isValidForType(offset, c) &&
|
|
isValidForType(modulus, c));
|
|
}
|
|
}
|