/**
* Copyright (c) <2013> <Radware Ltd.> and others. All rights reserved.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License
* v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
* @author Gera Goft
* @version 0.1
*/
package org.opendaylight.defense4all.framework.core.impl;
import org.opendaylight.defense4all.framework.core.ExceptionControlApp;
import org.opendaylight.defense4all.framework.core.FrameworkMain;
import org.opendaylight.defense4all.framework.core.HealthTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HealthTrackerImpl implements HealthTracker {
private static final int PERCENTAGE_OF_HEALTH_IMROVEMENT_PER_MINUTE = 10;
private static final int MINIMAL_TIME_IN_MINUTES_BETWEEN_FR_HEALTH_LOGS = 1;
static Logger log = LoggerFactory.getLogger(HealthTrackerImpl.class);
/* request shutdown is dedicated thread */
class ShutdownThread implements Runnable {
boolean graceful;
public ShutdownThread(boolean graceful) {this.graceful = graceful;}
public synchronized void run() {
while ( true ) {
fMain.requestShutdown(graceful);
}
}
}
protected FrameworkMain fMain;
protected int healthLevel; // Maximum is maxHealthLevel(100%). Shutdown is requested below threshold.
protected long lastReportTime;
protected int minimalHealthThreshold;
protected boolean shutdownRequested;
protected int maxHealthLevel = 100; // Maximum is 100% if not permanent issue has reported
public HealthTrackerImpl() {healthLevel = 100; lastReportTime = System.currentTimeMillis(); shutdownRequested = false;}
/* Setters for Spring */
public void setFrameworkMain(FrameworkMain frameworkMain) {this.fMain = frameworkMain;}
public void setMinimalHealthThreshold(int threshold) {this.minimalHealthThreshold = threshold;}
/** ####
* @param param_name param description
* @throws ExceptionControlApp
* @throws exception_type circumstances description
*/
@Override
public synchronized void reportHealthIssue(int issueLevel) {
reportHealthIssueSynchronized(issueLevel);
}
protected void reportHealthIssueSynchronized(int issueLevel) {
long currentTime = System.currentTimeMillis();
long timeFromLastReportInMins = (currentTime - lastReportTime) / 60000;
/* Check if graceful termination was requested more than 1 minute ago - so immediate termination is needed. */
if(shutdownRequested && timeFromLastReportInMins >= 1) {
fMain.requestShutdown(false); // Request immediate shutdown
return;
}
/* Update health level according to "healing" time passed. */
healthLevel += ((int) timeFromLastReportInMins) * PERCENTAGE_OF_HEALTH_IMROVEMENT_PER_MINUTE;
if(healthLevel > maxHealthLevel) healthLevel = maxHealthLevel;
if(!shutdownRequested)
lastReportTime = currentTime;
/* Add the new "illness". */
healthLevel -= issueLevel;
/* Log health in flight recorder */
if(timeFromLastReportInMins > MINIMAL_TIME_IN_MINUTES_BETWEEN_FR_HEALTH_LOGS)
log.info ( "Health level is " + healthLevel + "%");
if(healthLevel >= minimalHealthThreshold) return;
/* Health is below threshold level, so request graceful termination.
* Launch shutdown request in dedicated thread to prevent possible deadlocks on finit operations */
if(!shutdownRequested) {
shutdownRequested = true;
log.warn( "Initiating shutdown because health level "
+ healthLevel + "% is below threshold level of " + minimalHealthThreshold);
ShutdownThread shutdownThread = new ShutdownThread(true);
shutdownThread.run();
fMain.requestShutdown(true);
}
}
@Override
public synchronized void reportHealthIssue(int issueLevel, boolean permanent) {
if ( permanent == false) {
// just report health issue
reportHealthIssueSynchronized (issueLevel );
} else {
// permanent health issue - decrease max
maxHealthLevel -= issueLevel;
if ( maxHealthLevel < 0) maxHealthLevel = 0;
// report 0 health issue to check current value against new maximum
reportHealthIssueSynchronized ( 0 );
}
}
}