package ddth.dasp.framework.scheduletask;
import java.text.MessageFormat;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddth.dasp.common.id.IdGenerator;
public abstract class AbstractTaskRegistry implements ITaskRegistry {
private final Logger LOGGER = LoggerFactory.getLogger(AbstractTaskRegistry.class);
private boolean valid = true;
private BlockingQueue<TaskSchedulingInfo> taskSchedulingBuffer = new LinkedBlockingQueue<TaskSchedulingInfo>(
1024);
public void init() {
Thread bufferWatcherThread = new Thread() {
public void run() {
while (!interrupted() && valid) {
try {
TaskSchedulingInfo schedulingInfo = taskSchedulingBuffer.poll();
if (schedulingInfo != null) {
if (!_scheduleTask(schedulingInfo)) {
taskSchedulingBuffer.offer(schedulingInfo);
}
}
Thread.yield();
// try {
// Thread.sleep(5000);
// } catch (InterruptedException e) {
// }
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
}
}
};
bufferWatcherThread.setPriority(Thread.MIN_PRIORITY);
// bufferWatcherThread.setName(HazelcastLocalRunClusterStatusTaskRegistry.class.getName());
bufferWatcherThread.setDaemon(true);
bufferWatcherThread.start();
}
public void destroy() {
valid = false;
}
/*---------- storage methods ----------*/
protected abstract boolean storeTaskSchedulingInfo(TaskSchedulingInfo schedulingInfo);
protected abstract TaskSchedulingInfo retrieveTaskSchedulingInfo(String taskId);
protected abstract boolean removeTaskSchedulingInfo(String taskId);
protected abstract ITask.Status getTaskStatus(String taskId);
protected abstract void preRunning(String taskId);
protected abstract void postRunning(String taskId);
/*---------- storage methods ----------*/
// protected abstract void scheduleToRun(TaskSchedulingInfo schedulingInfo,
// boolean firstTime);
protected abstract void scheduleToRun(String taskId, boolean firstTime);
private boolean _scheduleTask(TaskSchedulingInfo schedulingInfo) {
try {
ITask task = schedulingInfo.getTask();
String taskId = task.getId();
TaskSchedulingInfo oldSchedulingInfo = retrieveTaskSchedulingInfo(taskId);
if (storeTaskSchedulingInfo(schedulingInfo)) {
if (oldSchedulingInfo == null) {
// new task registration, schedule to run
// scheduleToRun(schedulingInfo, true);
scheduleToRun(taskId, true);
}
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean scheduleTask(TaskSchedulingInfo schedulingInfo) {
if (!valid) {
return false;
}
return taskSchedulingBuffer.offer(schedulingInfo);
}
/**
* {@inheritDoc}
*/
@Override
public boolean unscheduleTask(String taskId) {
return removeTaskSchedulingInfo(taskId);
}
/**
* {@inheritDoc}
*/
@Override
public boolean unscheduleTask(ITask task) {
return removeTaskSchedulingInfo(task.getId());
}
/**
* {@inheritDoc}
*/
@Override
public TaskSchedulingInfo getTaskSchedulingInfo(String taskId) {
return retrieveTaskSchedulingInfo(taskId);
}
/**
* {@inheritDoc}
*/
@Override
public TaskSchedulingInfo getTaskSchedulingInfo(ITask task) {
return retrieveTaskSchedulingInfo(task.getId());
}
/**
* {@inheritDoc}
*/
@Override
public boolean isRunning(ITask task) {
return isRunning(task.getId());
}
/**
* {@inheritDoc}
*/
@Override
public boolean isRunning(String taskId) {
ITask.Status taskStatus = getTaskStatus(taskId);
return taskStatus != null && taskStatus == ITask.Status.RUNNING;
}
protected abstract class TaskRunner implements Runnable {
private TaskSchedulingInfo schedulingInfo;
public TaskRunner(TaskSchedulingInfo schedulingInfo) {
this.schedulingInfo = schedulingInfo;
}
protected TaskSchedulingInfo getSchedulingInfo() {
return schedulingInfo;
}
protected void logTaskExecution(String runId, ITask task, Object params, Object output,
long startTimestamp, long endTimestamp, Throwable exception) {
String taskId = task.getId();
long duration = endTimestamp - startTimestamp;
String msg = "Run: {0}\n- Task {1} finished in {2} ms; exception: {3}.\n- Input: {4}\n- Output: {5}\n";
msg = MessageFormat.format(msg, runId, taskId, duration,
exception != null ? exception.getMessage() : null, params, output);
if (exception != null) {
LOGGER.debug(msg, exception);
} else {
LOGGER.debug(msg);
}
}
@Override
public void run() {
ITask task = schedulingInfo.getTask();
String taskId = task.getId();
if (isRunning(taskId) && !task.isAllowConcurrent()) {
return;
}
long startTimestamp = System.currentTimeMillis();
String runId = IdGenerator.getInstance(IdGenerator.getMacAddr()).generateId64Hex();
Throwable exception = null;
Object params = schedulingInfo.getParams();
Object output = null;
preRunning(taskId);
try {
output = internalRunTask(task, params);
} catch (Throwable t) {
exception = t;
} finally {
postRunning(taskId);
long endTimestamp = System.currentTimeMillis();
logTaskExecution(runId, task, params, output, startTimestamp, endTimestamp,
exception);
switch (schedulingInfo.getScheduling()) {
case CONTINUOUS:
case REPEATED:
// scheduleToRun(schedulingInfo, false);
scheduleToRun(taskId, false);
case RUNONCE:
break;
}
}
}
/**
* Sub-class overrides this method to implement its own business.
*
* @param task
* @param params
* @return
*/
protected abstract Object internalRunTask(ITask task, Object params);
}
}