/*
* Copyright 2008 the original author or authors.
* Copyright 2005 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.impl.watch;
import org.rioproject.watch.Calculable;
import org.rioproject.watch.ThresholdType;
import org.rioproject.watch.ThresholdValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The BoundedThresholdManager provides support for threshold handling as
* follows: A ThresholdNotify.notify method is invoked when the high threshold
* is breached, and again invoked when the Calculable drops below the high
* threshold. Low threshold processing occurs in the same manner
*/
public class BoundedThresholdManager extends ThresholdManager {
private boolean thresholdCrossed = false;
private static final int CLEARED = 0;
private static final int BREACHED_LOWER = 1;
private static final int BREACHED_UPPER = 2;
private int direction = 0;
private final String id;
static Logger logger = LoggerFactory.getLogger("org.rioproject.watch");
public BoundedThresholdManager(String id) {
this.id = id;
}
public boolean getThresholdCrossed() {
return (thresholdCrossed);
}
@Override
protected String getID() {
return id;
}
public void checkThreshold(Calculable calculable) {
ThresholdValues thresholdValues = getThresholdValues();
double value = calculable.getValue();
if(thresholdCrossed) {
if(direction == BREACHED_UPPER) {
if(value < thresholdValues.getHighThreshold()) {
thresholdCrossed = false;
direction = CLEARED;
/* the next 2 lines produce a cleared event*/
thresholdValues.incThresholdClearedCount();
notifyListeners(calculable, ThresholdType.CLEARED);
checkLowThresholdBreach(calculable);
} else {
checkHighThresholdBreach(calculable);
}
} else if(direction == BREACHED_LOWER) {
if(value > thresholdValues.getLowThreshold()) {
thresholdCrossed = false;
direction = CLEARED;
thresholdValues.incThresholdClearedCount();
notifyListeners(calculable, ThresholdType.CLEARED);
checkHighThresholdBreach(calculable);
} else {
checkLowThresholdBreach(calculable);
}
}
} else {
checkHighThresholdBreach(calculable);
checkLowThresholdBreach(calculable);
}
}
/**
* Check if the Calculable has crossed the high threshold
*
* @param calculable The Calculable value to check
*/
private void checkHighThresholdBreach(Calculable calculable) {
double value = calculable.getValue();
if(value > thresholdValues.getHighThreshold()) {
boolean notify;
if(thresholdValues.getStep()>0 && thresholdCrossed) {
double diff = value - thresholdValues.getCurrentHighThreshold();
notify = diff >= thresholdValues.getStep();
} else {
notify = true;
}
if(notify) {
thresholdCrossed = true;
direction = BREACHED_UPPER;
thresholdValues.incThresholdBreachedCount();
thresholdValues.setCurrentHighThreshold(value);
notifyListeners(calculable, ThresholdType.BREACHED);
}
}
}
/**
* Check if the Calculable has crossed the low threshold
*
* @param calculable The Calculable value to check
*/
private void checkLowThresholdBreach(Calculable calculable) {
double value = calculable.getValue();
if(value < thresholdValues.getLowThreshold()) {
boolean notify;
if(thresholdValues.getStep()>0 && thresholdCrossed) {
double diff = Math.abs(thresholdValues.getCurrentLowThreshold()-value);
notify = diff >= thresholdValues.getStep();
} else {
notify = true;
}
if(notify) {
thresholdCrossed = true;
direction = BREACHED_LOWER;
thresholdValues.incThresholdBreachedCount();
thresholdValues.setCurrentLowThreshold(value);
notifyListeners(calculable, ThresholdType.BREACHED);
}
}
}
}