package edu.harvard.mcb.leschziner.distributed;
import java.io.Serializable;
import edu.harvard.mcb.leschziner.event.CompletionEvent;
import edu.harvard.mcb.leschziner.event.ErrorEvent;
import edu.harvard.mcb.leschziner.storage.DefaultStorageEngine;
import edu.harvard.mcb.leschziner.storage.StorageEngine;
public abstract class DistributedProcessingTask implements
Serializable,
Runnable {
/**
*
*/
private static final long serialVersionUID = -7555516754323196893L;
// SUFFIXES for counters of task activity
public static final String PENDING_SUFFIX = "_pending";
public static final String ACTIVE_SUFFIX = "_active";
public static final String EVENT_SUFFIX = "_event";
// Number of objects produced by this task
protected long outputCount = 1;
// Name of distributed executor which handles the task
private final String executorName;
/**
* Build a new task that can be distributed for execution
*
* @param executorName
*/
public DistributedProcessingTask(String executorName) {
this.executorName = executorName;
}
/**
* Actually do whatever the task must do
*/
public abstract void process();
/**
* Run the task, noting its completion in the pending and activity trackers
* when it finishes
*/
@Override public void run() {
long startTime = System.currentTimeMillis();
try {
process();
} catch (Exception e) {
// Sandbox the processing
markError("", e, 0);
}
markComplete(System.currentTimeMillis() - startTime);
}
/**
* Mark this task pending, noting that it hasn't been completed and may be
* either queued or actively underway.
*/
public void markPending() {
DefaultStorageEngine.getStorageEngine()
.getAtomicNumber(executorName + PENDING_SUFFIX)
.incrementAndGet();
}
/**
* Mark this task as actively being run
*/
public void markActive() {
DefaultStorageEngine.getStorageEngine()
.getAtomicNumber(executorName + ACTIVE_SUFFIX)
.incrementAndGet();
}
/**
* Report an error on this task
*
* @param error
*/
protected void markError(String error, int lineNumber) {
System.err.println("Error on " + this + ": " + error);
DefaultStorageEngine.getStorageEngine()
.getBufferedQueue(executorName + EVENT_SUFFIX)
.add(new ErrorEvent(this.getClass().getName(),
error,
lineNumber));
}
/**
* Report an error on this task, with the exception that caused it
*
* @param error
* @param e
*/
public void markError(String error, Exception e, int lineNumber) {
String errorString = error + ": " + e.getMessage();
System.err.println(errorString);
DefaultStorageEngine.getStorageEngine()
.getBufferedQueue(executorName + EVENT_SUFFIX)
.add(new ErrorEvent(this.getClass().getName(),
errorString,
lineNumber,
e.getClass().getSimpleName()));
}
/**
* Mark this task complete
*/
private void markComplete(long runtime) {
StorageEngine storage = DefaultStorageEngine.getStorageEngine();
storage.getAtomicNumber(executorName + PENDING_SUFFIX)
.decrementAndGet();
storage.getAtomicNumber(executorName + ACTIVE_SUFFIX).decrementAndGet();
// Put an event on our event queue
storage.getBufferedQueue(executorName + EVENT_SUFFIX)
.add(new CompletionEvent(this.getClass().getName(),
runtime,
outputCount));
}
}