0N/A/*
2362N/A * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.management.monitor;
0N/A
0N/Aimport static com.sun.jmx.defaults.JmxProperties.MONITOR_LOGGER;
0N/Aimport java.util.logging.Level;
0N/Aimport javax.management.ObjectName;
0N/Aimport javax.management.MBeanNotificationInfo;
0N/Aimport static javax.management.monitor.Monitor.NumericalType.*;
0N/Aimport static javax.management.monitor.MonitorNotification.*;
0N/A
0N/A/**
0N/A * Defines a monitor MBean designed to observe the values of a counter
0N/A * attribute.
0N/A *
0N/A * <P> A counter monitor sends a {@link
0N/A * MonitorNotification#THRESHOLD_VALUE_EXCEEDED threshold
0N/A * notification} when the value of the counter reaches or exceeds a
0N/A * threshold known as the comparison level. The notify flag must be
0N/A * set to <CODE>true</CODE>.
0N/A *
0N/A * <P> In addition, an offset mechanism enables particular counting
0N/A * intervals to be detected. If the offset value is not zero,
0N/A * whenever the threshold is triggered by the counter value reaching a
0N/A * comparison level, that comparison level is incremented by the
0N/A * offset value. This is regarded as taking place instantaneously,
0N/A * that is, before the count is incremented. Thus, for each level,
0N/A * the threshold triggers an event notification every time the count
0N/A * increases by an interval equal to the offset value.
0N/A *
0N/A * <P> If the counter can wrap around its maximum value, the modulus
0N/A * needs to be specified. The modulus is the value at which the
0N/A * counter is reset to zero.
0N/A *
0N/A * <P> If the counter difference mode is used, the value of the
0N/A * derived gauge is calculated as the difference between the observed
0N/A * counter values for two successive observations. If this difference
0N/A * is negative, the value of the derived gauge is incremented by the
0N/A * value of the modulus. The derived gauge value (V[t]) is calculated
0N/A * using the following method:
0N/A *
0N/A * <UL>
0N/A * <LI>if (counter[t] - counter[t-GP]) is positive then
0N/A * V[t] = counter[t] - counter[t-GP]
0N/A * <LI>if (counter[t] - counter[t-GP]) is negative then
0N/A * V[t] = counter[t] - counter[t-GP] + MODULUS
0N/A * </UL>
0N/A *
0N/A * This implementation of the counter monitor requires the observed
0N/A * attribute to be of the type integer (<CODE>Byte</CODE>,
0N/A * <CODE>Integer</CODE>, <CODE>Short</CODE>, <CODE>Long</CODE>).
0N/A *
0N/A *
0N/A * @since 1.5
0N/A */
0N/Apublic class CounterMonitor extends Monitor implements CounterMonitorMBean {
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * PACKAGE CLASSES
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A static class CounterMonitorObservedObject extends ObservedObject {
0N/A
0N/A public CounterMonitorObservedObject(ObjectName observedObject) {
0N/A super(observedObject);
0N/A }
0N/A
0N/A public final synchronized Number getThreshold() {
0N/A return threshold;
0N/A }
0N/A public final synchronized void setThreshold(Number threshold) {
0N/A this.threshold = threshold;
0N/A }
0N/A public final synchronized Number getPreviousScanCounter() {
0N/A return previousScanCounter;
0N/A }
0N/A public final synchronized void setPreviousScanCounter(
0N/A Number previousScanCounter) {
0N/A this.previousScanCounter = previousScanCounter;
0N/A }
0N/A public final synchronized boolean getModulusExceeded() {
0N/A return modulusExceeded;
0N/A }
0N/A public final synchronized void setModulusExceeded(
0N/A boolean modulusExceeded) {
0N/A this.modulusExceeded = modulusExceeded;
0N/A }
0N/A public final synchronized Number getDerivedGaugeExceeded() {
0N/A return derivedGaugeExceeded;
0N/A }
0N/A public final synchronized void setDerivedGaugeExceeded(
0N/A Number derivedGaugeExceeded) {
0N/A this.derivedGaugeExceeded = derivedGaugeExceeded;
0N/A }
0N/A public final synchronized boolean getDerivedGaugeValid() {
0N/A return derivedGaugeValid;
0N/A }
0N/A public final synchronized void setDerivedGaugeValid(
0N/A boolean derivedGaugeValid) {
0N/A this.derivedGaugeValid = derivedGaugeValid;
0N/A }
0N/A public final synchronized boolean getEventAlreadyNotified() {
0N/A return eventAlreadyNotified;
0N/A }
0N/A public final synchronized void setEventAlreadyNotified(
0N/A boolean eventAlreadyNotified) {
0N/A this.eventAlreadyNotified = eventAlreadyNotified;
0N/A }
0N/A public final synchronized NumericalType getType() {
0N/A return type;
0N/A }
0N/A public final synchronized void setType(NumericalType type) {
0N/A this.type = type;
0N/A }
0N/A
0N/A private Number threshold;
0N/A private Number previousScanCounter;
0N/A private boolean modulusExceeded;
0N/A private Number derivedGaugeExceeded;
0N/A private boolean derivedGaugeValid;
0N/A private boolean eventAlreadyNotified;
0N/A private NumericalType type;
0N/A }
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * PRIVATE VARIABLES
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A /**
0N/A * Counter modulus.
0N/A * <BR>The default value is a null Integer object.
0N/A */
0N/A private Number modulus = INTEGER_ZERO;
0N/A
0N/A /**
0N/A * Counter offset.
0N/A * <BR>The default value is a null Integer object.
0N/A */
0N/A private Number offset = INTEGER_ZERO;
0N/A
0N/A /**
0N/A * Flag indicating if the counter monitor notifies when exceeding
0N/A * the threshold. The default value is set to
0N/A * <CODE>false</CODE>.
0N/A */
0N/A private boolean notify = false;
0N/A
0N/A /**
0N/A * Flag indicating if the counter difference mode is used. If the
0N/A * counter difference mode is used, the derived gauge is the
0N/A * difference between two consecutive observed values. Otherwise,
0N/A * the derived gauge is directly the value of the observed
0N/A * attribute. The default value is set to <CODE>false</CODE>.
0N/A */
0N/A private boolean differenceMode = false;
0N/A
0N/A /**
0N/A * Initial counter threshold. This value is used to initialize
0N/A * the threshold when a new object is added to the list and reset
0N/A * the threshold to its initial value each time the counter
0N/A * resets.
0N/A */
0N/A private Number initThreshold = INTEGER_ZERO;
0N/A
0N/A private static final String[] types = {
0N/A RUNTIME_ERROR,
0N/A OBSERVED_OBJECT_ERROR,
0N/A OBSERVED_ATTRIBUTE_ERROR,
0N/A OBSERVED_ATTRIBUTE_TYPE_ERROR,
0N/A THRESHOLD_ERROR,
0N/A THRESHOLD_VALUE_EXCEEDED
0N/A };
0N/A
0N/A private static final MBeanNotificationInfo[] notifsInfo = {
0N/A new MBeanNotificationInfo(
0N/A types,
0N/A "javax.management.monitor.MonitorNotification",
0N/A "Notifications sent by the CounterMonitor MBean")
0N/A };
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * CONSTRUCTORS
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A /**
0N/A * Default constructor.
0N/A */
0N/A public CounterMonitor() {
0N/A }
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * PUBLIC METHODS
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A /**
0N/A * Starts the counter monitor.
0N/A */
0N/A public synchronized void start() {
0N/A if (isActive()) {
0N/A MONITOR_LOGGER.logp(Level.FINER, CounterMonitor.class.getName(),
0N/A "start", "the monitor is already active");
0N/A return;
0N/A }
0N/A // Reset values.
0N/A //
0N/A for (ObservedObject o : observedObjects) {
0N/A final CounterMonitorObservedObject cmo =
0N/A (CounterMonitorObservedObject) o;
0N/A cmo.setThreshold(initThreshold);
0N/A cmo.setModulusExceeded(false);
0N/A cmo.setEventAlreadyNotified(false);
0N/A cmo.setPreviousScanCounter(null);
0N/A }
0N/A doStart();
0N/A }
0N/A
0N/A /**
0N/A * Stops the counter monitor.
0N/A */
0N/A public synchronized void stop() {
0N/A doStop();
0N/A }
0N/A
0N/A // GETTERS AND SETTERS
0N/A //--------------------
0N/A
0N/A /**
0N/A * Gets the derived gauge of the specified object, if this object is
0N/A * contained in the set of observed MBeans, or <code>null</code> otherwise.
0N/A *
0N/A * @param object the name of the object whose derived gauge is to
0N/A * be returned.
0N/A *
0N/A * @return The derived gauge of the specified object.
0N/A *
0N/A */
710N/A @Override
0N/A public synchronized Number getDerivedGauge(ObjectName object) {
0N/A return (Number) super.getDerivedGauge(object);
0N/A }
0N/A
0N/A /**
0N/A * Gets the derived gauge timestamp of the specified object, if
0N/A * this object is contained in the set of observed MBeans, or
0N/A * <code>0</code> otherwise.
0N/A *
0N/A * @param object the name of the object whose derived gauge
0N/A * timestamp is to be returned.
0N/A *
0N/A * @return The derived gauge timestamp of the specified object.
0N/A *
0N/A */
710N/A @Override
0N/A public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
0N/A return super.getDerivedGaugeTimeStamp(object);
0N/A }
0N/A
0N/A /**
0N/A * Gets the current threshold value of the specified object, if
0N/A * this object is contained in the set of observed MBeans, or
0N/A * <code>null</code> otherwise.
0N/A *
0N/A * @param object the name of the object whose threshold is to be
0N/A * returned.
0N/A *
0N/A * @return The threshold value of the specified object.
0N/A *
0N/A */
0N/A public synchronized Number getThreshold(ObjectName object) {
0N/A final CounterMonitorObservedObject o =
0N/A (CounterMonitorObservedObject) getObservedObject(object);
0N/A if (o == null)
0N/A return null;
0N/A
0N/A // If the counter that is monitored rolls over when it reaches a
0N/A // maximum value, then the modulus value needs to be set to that
0N/A // maximum value. The threshold will then also roll over whenever
0N/A // it strictly exceeds the modulus value. When the threshold rolls
0N/A // over, it is reset to the value that was specified through the
0N/A // latest call to the monitor's setInitThreshold method, before
0N/A // any offsets were applied.
0N/A //
0N/A if (offset.longValue() > 0L &&
0N/A modulus.longValue() > 0L &&
0N/A o.getThreshold().longValue() > modulus.longValue()) {
0N/A return initThreshold;
0N/A } else {
0N/A return o.getThreshold();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the initial threshold value common to all observed objects.
0N/A *
0N/A * @return The initial threshold.
0N/A *
0N/A * @see #setInitThreshold
0N/A *
0N/A */
0N/A public synchronized Number getInitThreshold() {
0N/A return initThreshold;
0N/A }
0N/A
0N/A /**
0N/A * Sets the initial threshold value common to all observed objects.
0N/A *
0N/A * <BR>The current threshold of every object in the set of
0N/A * observed MBeans is updated consequently.
0N/A *
0N/A * @param value The initial threshold value.
0N/A *
0N/A * @exception IllegalArgumentException The specified
0N/A * threshold is null or the threshold value is less than zero.
0N/A *
0N/A * @see #getInitThreshold
0N/A *
0N/A */
0N/A public synchronized void setInitThreshold(Number value)
0N/A throws IllegalArgumentException {
0N/A
0N/A if (value == null) {
0N/A throw new IllegalArgumentException("Null threshold");
0N/A }
0N/A if (value.longValue() < 0L) {
0N/A throw new IllegalArgumentException("Negative threshold");
0N/A }
0N/A
0N/A if (initThreshold.equals(value))
0N/A return;
0N/A initThreshold = value;
0N/A
0N/A // Reset values.
0N/A //
0N/A int index = 0;
0N/A for (ObservedObject o : observedObjects) {
0N/A resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
0N/A final CounterMonitorObservedObject cmo =
0N/A (CounterMonitorObservedObject) o;
0N/A cmo.setThreshold(value);
0N/A cmo.setModulusExceeded(false);
0N/A cmo.setEventAlreadyNotified(false);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the derived gauge of the first object in the set of
0N/A * observed MBeans.
0N/A *
0N/A * @return The derived gauge.
0N/A *
0N/A * @deprecated As of JMX 1.2, replaced by
0N/A * {@link #getDerivedGauge(ObjectName)}
0N/A */
0N/A @Deprecated
0N/A public synchronized Number getDerivedGauge() {
0N/A if (observedObjects.isEmpty()) {
0N/A return null;
0N/A } else {
0N/A return (Number) observedObjects.get(0).getDerivedGauge();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the derived gauge timestamp of the first object in the set
0N/A * of observed MBeans.
0N/A *
0N/A * @return The derived gauge timestamp.
0N/A *
0N/A * @deprecated As of JMX 1.2, replaced by
0N/A * {@link #getDerivedGaugeTimeStamp(ObjectName)}
0N/A */
0N/A @Deprecated
0N/A public synchronized long getDerivedGaugeTimeStamp() {
0N/A if (observedObjects.isEmpty()) {
0N/A return 0;
0N/A } else {
0N/A return observedObjects.get(0).getDerivedGaugeTimeStamp();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the threshold value of the first object in the set of
0N/A * observed MBeans.
0N/A *
0N/A * @return The threshold value.
0N/A *
0N/A * @see #setThreshold
0N/A *
0N/A * @deprecated As of JMX 1.2, replaced by {@link #getThreshold(ObjectName)}
0N/A */
0N/A @Deprecated
0N/A public synchronized Number getThreshold() {
0N/A return getThreshold(getObservedObject());
0N/A }
0N/A
0N/A /**
0N/A * Sets the initial threshold value.
0N/A *
0N/A * @param value The initial threshold value.
0N/A *
0N/A * @exception IllegalArgumentException The specified threshold is
0N/A * null or the threshold value is less than zero.
0N/A *
0N/A * @see #getThreshold()
0N/A *
0N/A * @deprecated As of JMX 1.2, replaced by {@link #setInitThreshold}
0N/A */
0N/A @Deprecated
0N/A public synchronized void setThreshold(Number value)
0N/A throws IllegalArgumentException {
0N/A setInitThreshold(value);
0N/A }
0N/A
0N/A /**
0N/A * Gets the offset value common to all observed MBeans.
0N/A *
0N/A * @return The offset value.
0N/A *
0N/A * @see #setOffset
0N/A */
0N/A public synchronized Number getOffset() {
0N/A return offset;
0N/A }
0N/A
0N/A /**
0N/A * Sets the offset value common to all observed MBeans.
0N/A *
0N/A * @param value The offset value.
0N/A *
0N/A * @exception IllegalArgumentException The specified
0N/A * offset is null or the offset value is less than zero.
0N/A *
0N/A * @see #getOffset
0N/A */
0N/A public synchronized void setOffset(Number value)
0N/A throws IllegalArgumentException {
0N/A
0N/A if (value == null) {
0N/A throw new IllegalArgumentException("Null offset");
0N/A }
0N/A if (value.longValue() < 0L) {
0N/A throw new IllegalArgumentException("Negative offset");
0N/A }
0N/A
0N/A if (offset.equals(value))
0N/A return;
0N/A offset = value;
0N/A
0N/A int index = 0;
0N/A for (ObservedObject o : observedObjects) {
0N/A resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the modulus value common to all observed MBeans.
0N/A *
0N/A * @see #setModulus
0N/A *
0N/A * @return The modulus value.
0N/A */
0N/A public synchronized Number getModulus() {
0N/A return modulus;
0N/A }
0N/A
0N/A /**
0N/A * Sets the modulus value common to all observed MBeans.
0N/A *
0N/A * @param value The modulus value.
0N/A *
0N/A * @exception IllegalArgumentException The specified
0N/A * modulus is null or the modulus value is less than zero.
0N/A *
0N/A * @see #getModulus
0N/A */
0N/A public synchronized void setModulus(Number value)
0N/A throws IllegalArgumentException {
0N/A
0N/A if (value == null) {
0N/A throw new IllegalArgumentException("Null modulus");
0N/A }
0N/A if (value.longValue() < 0L) {
0N/A throw new IllegalArgumentException("Negative modulus");
0N/A }
0N/A
0N/A if (modulus.equals(value))
0N/A return;
0N/A modulus = value;
0N/A
0N/A // Reset values.
0N/A //
0N/A int index = 0;
0N/A for (ObservedObject o : observedObjects) {
0N/A resetAlreadyNotified(o, index++, THRESHOLD_ERROR_NOTIFIED);
0N/A final CounterMonitorObservedObject cmo =
0N/A (CounterMonitorObservedObject) o;
0N/A cmo.setModulusExceeded(false);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the notification's on/off switch value common to all
0N/A * observed MBeans.
0N/A *
0N/A * @return <CODE>true</CODE> if the counter monitor notifies when
0N/A * exceeding the threshold, <CODE>false</CODE> otherwise.
0N/A *
0N/A * @see #setNotify
0N/A */
0N/A public synchronized boolean getNotify() {
0N/A return notify;
0N/A }
0N/A
0N/A /**
0N/A * Sets the notification's on/off switch value common to all
0N/A * observed MBeans.
0N/A *
0N/A * @param value The notification's on/off switch value.
0N/A *
0N/A * @see #getNotify
0N/A */
0N/A public synchronized void setNotify(boolean value) {
0N/A if (notify == value)
0N/A return;
0N/A notify = value;
0N/A }
0N/A
0N/A /**
0N/A * Gets the difference mode flag value common to all observed MBeans.
0N/A *
0N/A * @return <CODE>true</CODE> if the difference mode is used,
0N/A * <CODE>false</CODE> otherwise.
0N/A *
0N/A * @see #setDifferenceMode
0N/A */
0N/A public synchronized boolean getDifferenceMode() {
0N/A return differenceMode;
0N/A }
0N/A
0N/A /**
0N/A * Sets the difference mode flag value common to all observed MBeans.
0N/A *
0N/A * @param value The difference mode flag value.
0N/A *
0N/A * @see #getDifferenceMode
0N/A */
0N/A public synchronized void setDifferenceMode(boolean value) {
0N/A if (differenceMode == value)
0N/A return;
0N/A differenceMode = value;
0N/A
0N/A // Reset values.
0N/A //
0N/A for (ObservedObject o : observedObjects) {
0N/A final CounterMonitorObservedObject cmo =
0N/A (CounterMonitorObservedObject) o;
0N/A cmo.setThreshold(initThreshold);
0N/A cmo.setModulusExceeded(false);
0N/A cmo.setEventAlreadyNotified(false);
0N/A cmo.setPreviousScanCounter(null);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns a <CODE>NotificationInfo</CODE> object containing the
0N/A * name of the Java class of the notification and the notification
0N/A * types sent by the counter monitor.
0N/A */
710N/A @Override
0N/A public MBeanNotificationInfo[] getNotificationInfo() {
1128N/A return notifsInfo.clone();
0N/A }
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * PRIVATE METHODS
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A /**
0N/A * Updates the derived gauge attribute of the observed object.
0N/A *
0N/A * @param scanCounter The value of the observed attribute.
0N/A * @param o The observed object.
0N/A * @return <CODE>true</CODE> if the derived gauge value is valid,
0N/A * <CODE>false</CODE> otherwise. The derived gauge value is
0N/A * invalid when the differenceMode flag is set to
0N/A * <CODE>true</CODE> and it is the first notification (so we
0N/A * haven't 2 consecutive values to update the derived gauge).
0N/A */
0N/A private synchronized boolean updateDerivedGauge(
0N/A Object scanCounter, CounterMonitorObservedObject o) {
0N/A
0N/A boolean is_derived_gauge_valid;
0N/A
0N/A // The counter difference mode is used.
0N/A //
0N/A if (differenceMode) {
0N/A
0N/A // The previous scan counter has been initialized.
0N/A //
0N/A if (o.getPreviousScanCounter() != null) {
0N/A setDerivedGaugeWithDifference((Number)scanCounter, null, o);
0N/A
0N/A // If derived gauge is negative it means that the
0N/A // counter has wrapped around and the value of the
0N/A // threshold needs to be reset to its initial value.
0N/A //
0N/A if (((Number)o.getDerivedGauge()).longValue() < 0L) {
0N/A if (modulus.longValue() > 0L) {
0N/A setDerivedGaugeWithDifference((Number)scanCounter,
0N/A modulus, o);
0N/A }
0N/A o.setThreshold(initThreshold);
0N/A o.setEventAlreadyNotified(false);
0N/A }
0N/A is_derived_gauge_valid = true;
0N/A }
0N/A // The previous scan counter has not been initialized.
0N/A // We cannot update the derived gauge...
0N/A //
0N/A else {
0N/A is_derived_gauge_valid = false;
0N/A }
0N/A o.setPreviousScanCounter((Number)scanCounter);
0N/A }
0N/A // The counter difference mode is not used.
0N/A //
0N/A else {
0N/A o.setDerivedGauge((Number)scanCounter);
0N/A is_derived_gauge_valid = true;
0N/A }
0N/A return is_derived_gauge_valid;
0N/A }
0N/A
0N/A /**
0N/A * Updates the notification attribute of the observed object
0N/A * and notifies the listeners only once if the notify flag
0N/A * is set to <CODE>true</CODE>.
0N/A * @param o The observed object.
0N/A */
0N/A private synchronized MonitorNotification updateNotifications(
0N/A CounterMonitorObservedObject o) {
0N/A
0N/A MonitorNotification n = null;
0N/A
0N/A // Send notification if notify is true.
0N/A //
0N/A if (!o.getEventAlreadyNotified()) {
0N/A if (((Number)o.getDerivedGauge()).longValue() >=
0N/A o.getThreshold().longValue()) {
0N/A if (notify) {
0N/A n = new MonitorNotification(THRESHOLD_VALUE_EXCEEDED,
0N/A this,
0N/A 0,
0N/A 0,
0N/A "",
0N/A null,
0N/A null,
0N/A null,
0N/A o.getThreshold());
0N/A }
0N/A if (!differenceMode) {
0N/A o.setEventAlreadyNotified(true);
0N/A }
0N/A }
0N/A } else {
0N/A if (MONITOR_LOGGER.isLoggable(Level.FINER)) {
0N/A final StringBuilder strb = new StringBuilder()
0N/A .append("The notification:")
0N/A .append("\n\tNotification observed object = ")
0N/A .append(o.getObservedObject())
0N/A .append("\n\tNotification observed attribute = ")
0N/A .append(getObservedAttribute())
0N/A .append("\n\tNotification threshold level = ")
0N/A .append(o.getThreshold())
0N/A .append("\n\tNotification derived gauge = ")
0N/A .append(o.getDerivedGauge())
0N/A .append("\nhas already been sent");
0N/A MONITOR_LOGGER.logp(Level.FINER, CounterMonitor.class.getName(),
0N/A "updateNotifications", strb.toString());
0N/A }
0N/A }
0N/A
0N/A return n;
0N/A }
0N/A
0N/A /**
0N/A * Updates the threshold attribute of the observed object.
0N/A * @param o The observed object.
0N/A */
0N/A private synchronized void updateThreshold(CounterMonitorObservedObject o) {
0N/A
0N/A // Calculate the new threshold value if the threshold has been
0N/A // exceeded and if the offset value is greater than zero.
0N/A //
0N/A if (((Number)o.getDerivedGauge()).longValue() >=
0N/A o.getThreshold().longValue()) {
0N/A
0N/A if (offset.longValue() > 0L) {
0N/A
0N/A // Increment the threshold until its value is greater
0N/A // than the one for the current derived gauge.
0N/A //
0N/A long threshold_value = o.getThreshold().longValue();
0N/A while (((Number)o.getDerivedGauge()).longValue() >=
0N/A threshold_value) {
0N/A threshold_value += offset.longValue();
0N/A }
0N/A
0N/A // Set threshold attribute.
0N/A //
0N/A switch (o.getType()) {
0N/A case INTEGER:
277N/A o.setThreshold(Integer.valueOf((int)threshold_value));
0N/A break;
0N/A case BYTE:
277N/A o.setThreshold(Byte.valueOf((byte)threshold_value));
0N/A break;
0N/A case SHORT:
277N/A o.setThreshold(Short.valueOf((short)threshold_value));
0N/A break;
0N/A case LONG:
277N/A o.setThreshold(Long.valueOf(threshold_value));
0N/A break;
0N/A default:
0N/A // Should never occur...
0N/A MONITOR_LOGGER.logp(Level.FINEST,
0N/A CounterMonitor.class.getName(),
0N/A "updateThreshold",
0N/A "the threshold type is invalid");
0N/A break;
0N/A }
0N/A
0N/A // If the counter can wrap around when it reaches
0N/A // its maximum and we are not dealing with counter
0N/A // differences then we need to reset the threshold
0N/A // to its initial value too.
0N/A //
0N/A if (!differenceMode) {
0N/A if (modulus.longValue() > 0L) {
0N/A if (o.getThreshold().longValue() >
0N/A modulus.longValue()) {
0N/A o.setModulusExceeded(true);
0N/A o.setDerivedGaugeExceeded(
0N/A (Number) o.getDerivedGauge());
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Threshold value has been modified so we can notify again.
0N/A //
0N/A o.setEventAlreadyNotified(false);
0N/A } else {
0N/A o.setModulusExceeded(true);
0N/A o.setDerivedGaugeExceeded((Number) o.getDerivedGauge());
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Sets the derived gauge of the specified observed object when the
0N/A * differenceMode flag is set to <CODE>true</CODE>. Integer types
0N/A * only are allowed.
0N/A *
0N/A * @param scanCounter The value of the observed attribute.
0N/A * @param mod The counter modulus value.
0N/A * @param o The observed object.
0N/A */
0N/A private synchronized void setDerivedGaugeWithDifference(
0N/A Number scanCounter, Number mod, CounterMonitorObservedObject o) {
0N/A /* We do the arithmetic using longs here even though the
0N/A result may end up in a smaller type. Since
0N/A l == (byte)l (mod 256) for any long l,
0N/A (byte) ((byte)l1 + (byte)l2) == (byte) (l1 + l2),
0N/A and likewise for subtraction. So it's the same as if
0N/A we had done the arithmetic in the smaller type.*/
0N/A
0N/A long derived =
0N/A scanCounter.longValue() - o.getPreviousScanCounter().longValue();
0N/A if (mod != null)
0N/A derived += modulus.longValue();
0N/A
0N/A switch (o.getType()) {
277N/A case INTEGER: o.setDerivedGauge(Integer.valueOf((int) derived)); break;
277N/A case BYTE: o.setDerivedGauge(Byte.valueOf((byte) derived)); break;
277N/A case SHORT: o.setDerivedGauge(Short.valueOf((short) derived)); break;
277N/A case LONG: o.setDerivedGauge(Long.valueOf(derived)); break;
0N/A default:
0N/A // Should never occur...
0N/A MONITOR_LOGGER.logp(Level.FINEST, CounterMonitor.class.getName(),
0N/A "setDerivedGaugeWithDifference",
0N/A "the threshold type is invalid");
0N/A break;
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * ------------------------------------------
0N/A * PACKAGE METHODS
0N/A * ------------------------------------------
0N/A */
0N/A
0N/A /**
0N/A * Factory method for ObservedObject creation.
0N/A *
0N/A * @since 1.6
0N/A */
0N/A @Override
0N/A ObservedObject createObservedObject(ObjectName object) {
0N/A final CounterMonitorObservedObject cmo =
0N/A new CounterMonitorObservedObject(object);
0N/A cmo.setThreshold(initThreshold);
0N/A cmo.setModulusExceeded(false);
0N/A cmo.setEventAlreadyNotified(false);
0N/A cmo.setPreviousScanCounter(null);
0N/A return cmo;
0N/A }
0N/A
0N/A /**
0N/A * This method globally sets the derived gauge type for the given
0N/A * "object" and "attribute" after checking that the type of the
0N/A * supplied observed attribute value is one of the value types
0N/A * supported by this monitor.
0N/A */
0N/A @Override
0N/A synchronized boolean isComparableTypeValid(ObjectName object,
0N/A String attribute,
0N/A Comparable<?> value) {
0N/A final CounterMonitorObservedObject o =
0N/A (CounterMonitorObservedObject) getObservedObject(object);
0N/A if (o == null)
0N/A return false;
0N/A
0N/A // Check that the observed attribute is of type "Integer".
0N/A //
0N/A if (value instanceof Integer) {
0N/A o.setType(INTEGER);
0N/A } else if (value instanceof Byte) {
0N/A o.setType(BYTE);
0N/A } else if (value instanceof Short) {
0N/A o.setType(SHORT);
0N/A } else if (value instanceof Long) {
0N/A o.setType(LONG);
0N/A } else {
0N/A return false;
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A @Override
0N/A synchronized Comparable<?> getDerivedGaugeFromComparable(
0N/A ObjectName object,
0N/A String attribute,
0N/A Comparable<?> value) {
0N/A final CounterMonitorObservedObject o =
0N/A (CounterMonitorObservedObject) getObservedObject(object);
0N/A if (o == null)
0N/A return null;
0N/A
0N/A // Check if counter has wrapped around.
0N/A //
0N/A if (o.getModulusExceeded()) {
0N/A if (((Number)o.getDerivedGauge()).longValue() <
0N/A o.getDerivedGaugeExceeded().longValue()) {
0N/A o.setThreshold(initThreshold);
0N/A o.setModulusExceeded(false);
0N/A o.setEventAlreadyNotified(false);
0N/A }
0N/A }
0N/A
0N/A // Update the derived gauge attributes and check the
0N/A // validity of the new value. The derived gauge value
0N/A // is invalid when the differenceMode flag is set to
0N/A // true and it is the first notification, i.e. we
0N/A // haven't got 2 consecutive values to update the
0N/A // derived gauge.
0N/A //
0N/A o.setDerivedGaugeValid(updateDerivedGauge(value, o));
0N/A
0N/A return (Comparable<?>) o.getDerivedGauge();
0N/A }
0N/A
0N/A @Override
0N/A synchronized void onErrorNotification(MonitorNotification notification) {
0N/A final CounterMonitorObservedObject o = (CounterMonitorObservedObject)
0N/A getObservedObject(notification.getObservedObject());
0N/A if (o == null)
0N/A return;
0N/A
0N/A // Reset values.
0N/A //
0N/A o.setModulusExceeded(false);
0N/A o.setEventAlreadyNotified(false);
0N/A o.setPreviousScanCounter(null);
0N/A }
0N/A
0N/A @Override
0N/A synchronized MonitorNotification buildAlarmNotification(
0N/A ObjectName object,
0N/A String attribute,
0N/A Comparable<?> value) {
0N/A final CounterMonitorObservedObject o =
0N/A (CounterMonitorObservedObject) getObservedObject(object);
0N/A if (o == null)
0N/A return null;
0N/A
0N/A // Notify the listeners and update the threshold if
0N/A // the updated derived gauge value is valid.
0N/A //
0N/A final MonitorNotification alarm;
0N/A if (o.getDerivedGaugeValid()) {
0N/A alarm = updateNotifications(o);
0N/A updateThreshold(o);
0N/A } else {
0N/A alarm = null;
0N/A }
0N/A return alarm;
0N/A }
0N/A
0N/A /**
0N/A * Tests if the threshold, offset and modulus of the specified observed
0N/A * object are of the same type as the counter. Only integer types are
0N/A * allowed.
0N/A *
0N/A * Note:
0N/A * If the optional offset or modulus have not been initialized, their
0N/A * default value is an Integer object with a value equal to zero.
0N/A *
0N/A * @param object The observed object.
0N/A * @param attribute The observed attribute.
0N/A * @param value The sample value.
0N/A * @return <CODE>true</CODE> if type is the same,
0N/A * <CODE>false</CODE> otherwise.
0N/A */
0N/A @Override
0N/A synchronized boolean isThresholdTypeValid(ObjectName object,
0N/A String attribute,
0N/A Comparable<?> value) {
0N/A final CounterMonitorObservedObject o =
0N/A (CounterMonitorObservedObject) getObservedObject(object);
0N/A if (o == null)
0N/A return false;
0N/A
0N/A Class<? extends Number> c = classForType(o.getType());
0N/A return (c.isInstance(o.getThreshold()) &&
0N/A isValidForType(offset, c) &&
0N/A isValidForType(modulus, c));
0N/A }
0N/A}