/* Copyright 1999-2008 Acelet.org. All rights reserved. GPL v2 license */
/** @author Wei Jiang */
package com.acelet.s.watchdog;
import java.io.*;
import java.net.*;
import java.util.*;
import com.acelet.lib.Common;
import com.acelet.lib.LoggingConstants;
import com.acelet.lib.LoggingTimeoutException;
import com.acelet.lib.Kit;
import com.acelet.lib.NotSupportedException;
import com.acelet.lib.Phrase;
import com.acelet.s.chore.*;
import com.acelet.s.job.Job;
import com.acelet.s.job.CreateJob;
public abstract class WatchTimerTask extends TimerTask implements Watchable {
protected static String hostname = "?";
protected static boolean logIncludesResult = false;
protected static Random random;
protected Chore comingChore;
protected WorkingChore workingChore;
protected Triggering triggering;
protected String toBrief;
protected String result = "";
protected int delay = 0;
protected long fromPeriod;
protected long toPeriod;
protected abstract Triggering setTrigger() throws Exception;
static {
random = new Random();
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
public WatchTimerTask() {
}
public boolean cancel() {
boolean flag = super.cancel();
try {
if (triggering != null) {
triggering.removeListener(this);
triggering.stop();
}
} catch (Exception ex) {
ex.printStackTrace();
}
triggering = null;
return flag;
}
protected void cleanup() {
try {
triggering.stop();
triggering = null;
comingChore.status = Chore.STATUS_INACTIVE;
Delegate.updateChore(comingChore, System.currentTimeMillis());
cancel();
Long theId = new Long(workingChore.getId0());
synchronized (Registry.timerTaskHashtable) {
Registry.timerTaskHashtable.remove(theId);
}
synchronized (Registry.watchTimerTaskHashtable) {
Registry.watchTimerTaskHashtable.remove(theId);
}
Timer timer = (Timer) Registry.timerTaskToTimerHashtable.get(this);
if (timer != null) {
timer.cancel();
synchronized (Registry.timerTaskToTimerHashtable) {
Registry.timerTaskToTimerHashtable.remove(this);
}
}
System.gc();
System.runFinalization();
System.gc();
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected static boolean createExecutorTimerTask(Chore comingChore, Triggering triggering)
throws Exception {
if (isDesired(comingChore) == false)
return false;
Hashtable nameToChoreHashtable = (Hashtable) Registry.nameToChoreHashtable.clone();
Job job = new CreateJob().createJob(comingChore, nameToChoreHashtable);
TimerTask timerTask = new CommonTimerTask(comingChore, job, triggering);
Timer timer = new Timer();
timer.schedule(timerTask, comingChore.delay);
Long theId = new Long(comingChore.getId());
TimerTask originalTimerTask = (TimerTask) Registry.timerTaskHashtable.put(theId, timerTask);
if (originalTimerTask != null)
originalTimerTask.cancel();
Registry.timerTaskToTimerHashtable.put(timerTask, timer);
return true;
}
protected static boolean createWatchTimerTask(Chore comingChore) throws Exception {
if (comingChore.status != Chore.STATUS_STANDBY)
return false;
if (isDesired(comingChore) == false)
return false;
int triggerType = comingChore.getTriggerType();
WatchTimerTask timerTask = new DefineTrigger().getTriggerObject(triggerType, comingChore);
timerTask.setChore(comingChore);
Timer timer = new Timer();
long firstTime = random.nextInt(500);
if (comingChore.fromPeriod > 0)
firstTime += comingChore.fromPeriod;
timer.schedule(timerTask, new Date(firstTime), Watchdogging.interval);
Long theId = new Long(comingChore.getId());
TimerTask originalTimerTask =
(TimerTask) Registry.watchTimerTaskHashtable.put(theId, timerTask);
if (originalTimerTask != null)
originalTimerTask.cancel();
Registry.timerTaskToTimerHashtable.put(timerTask, timer);
return true;
}
protected static boolean isDesired(Chore comingChore) {
String desiredHostnames = comingChore.hostname.trim();
if (desiredHostnames == null || desiredHostnames.length() == 0)
return true;
StringTokenizer st = new StringTokenizer(desiredHostnames, ",");
while (st.hasMoreTokens()) {
String aHostname = st.nextToken().trim();
if (aHostname.equalsIgnoreCase(hostname))
return true;
}
return false;
}
public void reportException(Throwable throwable) {
try {
String error = Kit.getExceptionStackTrace(throwable);
Delegate.sendAlarmEmailForChoreError(comingChore.alarmEmail, workingChore.name, error);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
long now = System.currentTimeMillis();
if (now < fromPeriod) {
return;
}
if (now > toPeriod) {
cleanup();
return;
}
}
public void setChore(Chore comingChore) throws Exception {
this.comingChore = comingChore;
workingChore = new WorkingChore(comingChore);
toBrief = ChoreText.getChoreBrief(comingChore);
delay = comingChore.delay;
fromPeriod = comingChore.fromPeriod;
toPeriod = comingChore.toPeriod;
triggering = setTrigger();
}
protected void signalError(Throwable throwable) {
String throwableString = "";
if (throwable != null)
throwableString = throwable.toString() + "; " + Kit.getExceptionStackTrace(throwable);
try {
long now = System.currentTimeMillis();
String error = Chore.TASK_ERROR + toBrief +
LoggingConstants.COMMON_DELIMITER + throwableString;
if (logIncludesResult)
error += LoggingConstants.COMMON_DELIMITER + result;
workingChore.status = WorkingChore.STATUS_ERROR;
workingChore.lastResult = error;
workingChore.modifiedAt = now;
Delegate.updateWorkingChore(workingChore);
try {
Delegate.writeLogMessageToDatabaseForWatchdog(error);
} catch (LoggingTimeoutException lte) {
Delegate.sendAlarmEmailForChoreError(comingChore.alarmEmail, comingChore.name,
Phrase.get("ER_LOGGING_TIMEOUT"));
}
Delegate.sendAlarmEmailForChoreError(comingChore.alarmEmail, workingChore.name, error);
} catch (Throwable th) {
th.printStackTrace();
} finally {
}
}
public void startTask() throws Exception {
createExecutorTimerTask(comingChore, triggering);
}
}