package net.juniper.contrail.watchdog;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
public enum TaskWatchDog implements Runnable {
AKER1, AKER2;
ConcurrentMap<Runnable, MonitoredTaskRecord> monitored;
ConcurrentHashMap<Runnable, MonitoredTaskRecord> completed;
private TaskWatchDog() {
monitored = new ConcurrentHashMap<Runnable, MonitoredTaskRecord>();
completed = new ConcurrentHashMap<Runnable, MonitoredTaskRecord>();
}
public static
ConcurrentMap<Runnable, MonitoredTaskRecord> getMonitoredTasks() {
return AKER1.monitored;
}
public static
ConcurrentMap<Runnable, MonitoredTaskRecord> getCompletedTasks() {
return AKER1.completed;
}
public static void startMonitoring(Runnable task,
String name,
long timeout, TimeUnit unit) {
AKER1.start(task, name, timeout, unit);
}
private void start(Runnable task,
String name,
long timeout, TimeUnit unit) {
if (task == null) {
throw new IllegalArgumentException("Null argument");
}
MonitoredTaskRecord tRec =
new MonitoredTaskRecord(Thread.currentThread(), timeout, unit);
tRec.name = name;
tRec.startTime = System.currentTimeMillis();
tRec.stackTrace = tRec.thread.getStackTrace();
monitored.put(task, tRec);
}
public static void stopMonitoring(Runnable task) {
AKER1.stop(task);
}
private void stop(Runnable task) {
if (monitored.containsKey(task)) {
MonitoredTaskRecord tRec = monitored.get(task);
tRec.stopTime = System.currentTimeMillis();
monitored.remove(task);
computeStats(task, tRec);
}
}
private void computeStats(Runnable task, MonitoredTaskRecord tRec) {
long time = tRec.stopTime - tRec.startTime;
if (AKER1.completed.containsKey(task)) {
if (time < tRec.minTime) {
tRec.minTime = time;
} else if (time > tRec.maxTime) {
tRec.maxTime = time;
}
tRec.avgTime = (tRec.count * tRec.avgTime)/(tRec.count+1)
+ time/(tRec.count+1);
tRec.count++;
} else {
tRec.count = 1;
tRec.minTime = tRec.maxTime = time;
tRec.avgTime = (double)time;
completed.put(task, tRec);
}
}
@Override
public void run() {
for (TaskWatchDog aker: TaskWatchDog.values()) {
if (this != aker) {
// this watch dog will be monitored by all other watch dogs
aker.start(this, name(), 60000, TimeUnit.MILLISECONDS);
}
}
for (ConcurrentHashMap.Entry<Runnable, MonitoredTaskRecord> entry:
monitored.entrySet()) {
MonitoredTaskRecord tRec = entry.getValue();
if (tRec.blocked) {
continue;
}
long time_now = System.currentTimeMillis();
if (tRec.startTime + tRec.timeout < time_now ) {
// task is blocked or taking too long
tRec.blocked = true;
}
tRec.stackTrace = tRec.thread.getStackTrace();
}
for (TaskWatchDog aker: TaskWatchDog.values()) {
if (this != aker) {
aker.stop(this);
}
}
}
}