package com.neverwinterdp.scribengin.dataflow.worker;
import com.neverwinterdp.registry.RegistryException;
import com.neverwinterdp.scribengin.dataflow.DataflowContainer;
import com.neverwinterdp.scribengin.dataflow.DataflowRegistry;
import com.neverwinterdp.scribengin.dataflow.DataflowTask;
import com.neverwinterdp.scribengin.dataflow.DataflowTaskDescriptor;
import com.neverwinterdp.vm.VMDescriptor;
public class DataflowTaskExecutor {
private DataflowTaskExecutorDescriptor executorDescriptor;
private DataflowContainer dataflowContainer ;
private ExecutorManagerThread executorManagerThread ;
public DataflowTaskExecutor(DataflowTaskExecutorDescriptor descriptor, DataflowContainer container) throws RegistryException {
executorDescriptor = descriptor;
dataflowContainer = container;
DataflowRegistry dataflowRegistry = dataflowContainer.getDataflowRegistry() ;
VMDescriptor vmDescriptor = dataflowContainer.getVMDescriptor() ;
dataflowRegistry.createTaskExecutor(vmDescriptor, descriptor);
}
public DataflowTaskExecutorDescriptor getDescriptor() { return this.executorDescriptor ; }
public void start() {
executorManagerThread = new ExecutorManagerThread();
executorManagerThread.start();
}
public void shutdown() throws Exception {
if(isAlive()) executorManagerThread.interrupt();
}
public boolean isAlive() {
if(executorManagerThread == null) return false;
return executorManagerThread.isAlive();
}
public void execute() {
executorDescriptor.setStatus(DataflowTaskExecutorDescriptor.Status.RUNNING);
DataflowTask dataflowTask = null;
DataflowRegistry dataflowRegistry = dataflowContainer.getDataflowRegistry();
VMDescriptor vmDescriptor = dataflowContainer.getVMDescriptor() ;
try {
while(true) {
DataflowTaskDescriptor taskDescriptor = dataflowRegistry.assignDataflowTask(vmDescriptor);
if(taskDescriptor == null) return;
executorDescriptor.addAssignedTask(taskDescriptor);
dataflowRegistry.updateTaskExecutor(vmDescriptor, executorDescriptor);
dataflowTask = new DataflowTask(dataflowContainer, taskDescriptor);
dataflowTask.init();
DataflowTaskExecutorThread executorThread = new DataflowTaskExecutorThread(dataflowTask);
executorThread.start();
executorThread.waitForTimeout(10000);
if(dataflowTask.isComplete()) dataflowTask.finish();
else dataflowTask.suspend();
}
} catch (InterruptedException e) {
System.err.println("detect shutdown interrupt for task " + dataflowTask.getDescriptor().getId());
dataflowTask.interrupt();
} catch (Exception e) {
e.printStackTrace();
} finally {
doExit();
}
}
void doExit() {
try {
DataflowRegistry dataflowRegistry = dataflowContainer.getDataflowRegistry();
VMDescriptor vmDescriptor = dataflowContainer.getVMDescriptor() ;
executorDescriptor.setStatus(DataflowTaskExecutorDescriptor.Status.TERMINATED);
dataflowRegistry.updateTaskExecutor(vmDescriptor, executorDescriptor);
} catch(Exception ex) {
ex.printStackTrace();
}
}
public class ExecutorManagerThread extends Thread {
public void run() {
execute();
}
}
public class DataflowTaskExecutorThread extends Thread {
DataflowTask dataflowtask;
private boolean terminated = false;
public DataflowTaskExecutorThread(DataflowTask dataflowtask) {
this.dataflowtask = dataflowtask;
}
public void run() {
try {
dataflowtask.run();
notifyTermination();
} catch(Exception ex) {
ex.printStackTrace();
}
}
synchronized public void notifyTermination() {
terminated = true;
notifyAll() ;
}
synchronized void waitForTimeout(long timeout) throws InterruptedException {
wait(timeout);
if(!terminated) dataflowtask.interrupt();
waitForTerminated();
}
synchronized void waitForTerminated() throws InterruptedException {
if(terminated) return ;
wait(3000);
}
}
}