package center.task;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import ru.vassaev.core.Pool;
import ru.vassaev.core.CallBackInterface;
import ru.vassaev.core.container.AppInfo;
import ru.vassaev.core.db.Manager;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.thread.Processed;
import ru.vassaev.core.util.Strings;
import center.task.TaskSchedulerInfo.Action;
import center.task.api.ATaskAPI;
import center.task.api.ITaskAPI;
import center.task.api.TaskCI;
import center.task.prm.Type;
import center.task.prm.tp.PrmFactory;
/**
* Главный поток исполнения приложения Center
*
* @author Vassaev A.V.
* @version 1.3 21.09.2013
*/
public class TaskExecutor implements Processed<AppInfo>,
CallBackInterface<ru.vassaev.core.thread.Process, Object> {
private Map<String, TaskInfo> hs = new TreeMap<String, TaskInfo>();
private Map<String, Object> consts = new TreeMap<String, Object>();
private String alias;
private Pool<ru.vassaev.core.thread.Process> prcpool = null;
private String prcpool_name;
private AppInfo ai;
private long id_processor;
private int block_wait = 3000;
private ArrayList<NewTaskInfo> starts = new ArrayList<NewTaskInfo>();
private Map<String, SchedulerTasks> schedulers = new HashMap<String, SchedulerTasks>();
private PrmFactory fact = new PrmFactory();
private ITaskAPI ta;
public void loadFromXML_X(Element root, boolean main) throws SysException {
String tn = root.getTagName();
if ((main && tn.equals("exec")) || (!main && tn.equals("include"))) {
if (main) {
alias = root.getAttribute("alias");
prcpool_name = root.getAttribute("prcpool");
block_wait = Strings.parseIntegerNvl(root.getAttribute("block_wait"),
3000);
boolean waiting = true;
do {
try {
ta = ATaskAPI.getInstance(root.getAttribute("task_api"),
center.task.api.db.TaskAPI.class, alias);
waiting = false;
} catch (SysException e) {
System.out.println("Waiting interface...");
try {
Thread.sleep(1000);// TODO нужен параметр
} catch (InterruptedException e1) {
throw new SysException(e1);
}
}
} while (waiting);
}
NodeList nl = root.getChildNodes();// Xml.getElementsByTagName(root,
// "task");
Node n;
Element el;
String nn;
for (int i = 0; i < nl.getLength(); i++) {
n = nl.item(i);
if (n.getNodeType() != Node.ELEMENT_NODE)
continue;
el = (Element) nl.item(i);
nn = el.getNodeName();
if (nn.equals("task"))
try {// Загрузить информацию по задаче
System.out
.print("Loading task " + el.getAttribute("name") + " ...");
String extend = el.getAttribute("extends");
TaskInfo ti_extend = null;
if (extend != null && !"".equals(extend)) {
ti_extend = hs.get(extend);
if (ti_extend == null)
new SysException("There is no extends \"" + extend
+ "\" for task " + el.getAttribute("cls"))
.printStackTrace();
}
TaskInfo ti = new TaskInfo();
ti.load(null, ti_extend, el);
hs.put(ti.clsName, ti);
System.out.println("\tOk");
} catch (Exception e) {
System.out.println("\t" + e.getMessage());
e.printStackTrace();
}
else if (nn.equals("start"))
try {// Загрузить информацию по запуску
NewTaskInfo nt = new NewTaskInfo();
nt.load(null, null, el);
starts.add(nt);
} catch (Exception e) {
e.printStackTrace();
}
else if (nn.equals("scheduler"))
try {// Загрузить информацию по расписанию
TaskSchedulerInfo nt = new TaskSchedulerInfo();
nt.load(null, null, el);
String nm = nt.getName();
schedulers.put(nm, new SchedulerTasks(nt));
} catch (Exception e) {
e.printStackTrace();
}
else if (nn.equals("const"))
try {// Загрузить информацию о константе
String name = Strings.getXMLValue(el, "#name");
String grp = Strings.getXMLValue(el, "#grp");
String fn = (grp == null || grp.length() == 0) ? name : grp + "/"
+ name;
Object o = fact.getParam(el, null);
if (o instanceof Type)
((Type) o).setCache(true);
consts.put(fn, o);
} catch (Exception e) {
e.printStackTrace();
}
else if (main && nn.equals("include"))
try {// Внешний файл
String fn = el.getTextContent();
if (fn == null || fn.length() == 0)
continue;
loadFromXML_X(this.ai.getContainer().getDocument(fn)
.getDocumentElement(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public Object callBack(ru.vassaev.core.thread.Process prc) {
prcpool.free(prc);
return null;
}
private class StartTasks implements Processed<ITaskAPI> {
public void processing(ITaskAPI ta) throws Throwable {
try {
for (NewTaskInfo nt : starts) {
nt.createAndReadyTask(ta, null, id_processor, null, null);
}
} finally {
prcpool.free(ru.vassaev.core.thread.Process.currentProcess());
}
}
}
private class SchedulerTasks implements Processed<ITaskAPI> {
public TaskSchedulerInfo sti;
private Object sync;
public SchedulerTasks(TaskSchedulerInfo sti) {
this.sti = sti;
this.sync = new Object();
}
public void processing(ITaskAPI ta) throws Throwable {
try {
System.out.println("Scheduler by name '" + sti.getName()
+ "' was started");
Action act;
Context cntx = new Context(id_processor, 0, ta, sti);
while (!Action.STOP.equals(act = sti.getAction(cntx))) {
if (Action.START.equals(act) || Action.ONES.equals(act)) {
cntx = sti.createAndReadyTask(cntx, null, null);
if (sti.getWaitFinished(cntx)) {
long duration = Strings.parseIntegerNvl(
sti.finish_duration.getValue(cntx), 0);
ta.waitFinished(cntx.id_subject, cntx.id_task, duration);
}
}
if (Action.ONES.equals(act))
break;
synchronized (sync) {
long w = sti.getPCS(cntx);
sync.wait(w * 1000);
}
cntx = new Context(id_processor, 0, ta, sti);
}
} finally {
System.out.println("Scheduler by name '" + sti.getName()
+ "' stoped its job");
prcpool.free(ru.vassaev.core.thread.Process.currentProcess());
}
}
}
public void processing(AppInfo ai) throws Throwable {
this.ai = ai;
Manager.setContainer(ai.getContainer());
Element el = ai.getDocInfo();
loadFromXML_X(el, true);
// -------------------------------------------------------------------------
// The Layout<V, E> is parameterized by the vertex and edge types
/*
* { final TaskInfo ti = hs.get("JAVA.QIWI.GW"); Layout<String, String>
* layout = new CircleLayout(ti.task_plan.getGraph()); layout.setSize(new
* Dimension(300, 300)); // sets the initial size of the space // The
* BasicVisualizationServer<V,E> is parameterized by the edge types
* VisualizationViewer<String, String> vv = new VisualizationViewer<String,
* String>(layout); new BasicVisualizationServer<String, String>(layout);
* vv.setPreferredSize(new Dimension(350, 350)); //Sets the viewing area
* size vv.getRenderContext().setVertexLabelTransformer(new
* ToStringLabeller()); DefaultModalGraphMouse gm = new
* DefaultModalGraphMouse(); gm.setMode(ModalGraphMouse.Mode.PICKING);
* vv.setGraphMouse(gm); Transformer<String, Paint> r = new
* Transformer<String, Paint>() { public Paint transform(String i) { return
* Color.GREEN; } }; vv.getRenderContext().setVertexDrawPaintTransformer(r);
* vv.getRenderContext().setVertexShapeTransformer(new Transformer<String,
* Shape>() {
*
* public Shape transform(String s) { String pref = s.substring(0, 4);
* String n = s.substring(4); Object p = ti.prms.get(n); if
* (pref.equals("PRM:")) { if (p == null) return new Rectangle(-10, -10, 20,
* 20); if (p instanceof IDependentParam) return new Arc2D.Double(-10, -10,
* 20, 20, 0, 360, 1); return new Rectangle(-20, -20, 40, 40); //To change
* body of implemented methods use File | Settings | File Templates. } if
* (pref.equals("TSK:")) { return new Arc2D.Double(-100, -100, 200, 200, 0,
* 360, 1); } return new Rectangle(-10, -10, 20, 20); } }); JFrame frame =
* new JFrame("Simple Graph View");
* frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
* frame.getContentPane().add(vv); frame.pack(); frame.setVisible(true); }//
*/
// -------------------------------------------------------------------------
if (prcpool_name == null)
prcpool_name = ai.getContainer().getRM().getMainThreadPool();
prcpool = (Pool<ru.vassaev.core.thread.Process>) ai.getContainer().getRM()
.getPool(prcpool_name);
if (prcpool == null)
throw new SysException("There is no process pool by name \""
+ prcpool_name + "\"");
System.out.println("Pool name is \"" + prcpool_name
+ "\" was set for the App");
boolean waiting = true;
do {
try {
id_processor = ta.getSubject(0);
ta.registerClasses(id_processor, hs.keySet());
waiting = false;
} catch (SysException e) {
System.out.println("Waiting interface...");
Thread.sleep(1000);// TODO нужен параметр
}
} while (waiting);
System.out.println("Task executer info has been loaded");
ru.vassaev.core.thread.Process prc = ru.vassaev.core.thread.Process
.currentProcess();
// Регистрируем текущий ID процессора для запуска заданий в пределах данного
// обработчика
prc.regResourceName(id_processor, "PROCESSOR_ID");
ta.log(id_processor, 0, "The processor's identifitier has been got", false);
ta.log(id_processor, 0, "\tprocessor's id = " + id_processor, false);
long sWait = 1000; // !!! нужен параметр
String[] cls_name = new String[1];
// Стартовать задачи
ru.vassaev.core.thread.Process sprc = prcpool.occupy();
sprc.setTarget(new StartTasks());
sprc.regResourceName(id_processor, "PROCESSOR_ID");
sprc.start(ta);
// Запустить schedulers
for (Map.Entry<String, SchedulerTasks> sch : schedulers.entrySet()) {
sprc = prcpool.occupy();
sprc.setTarget(sch.getValue());
sprc.regResourceName(id_processor, "PROCESSOR_ID");
sprc.start(ta);
}
long wait;
prc = null;
while (true) {
if (prc == null) {
// Ожидать свободного потока для задачи
while (prcpool.getMaxSizePool() <= prcpool.getBusySize()) {
try {
Thread.sleep(1000);// TODO нужен параметр
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Получить поток для выполнения
prc = prcpool.occupyWait();
// Процедура для выполнения после выполнения потока
prc.setCallBackOnEndProcess(this);
}
long id_task;
TaskCI tci = null;
try {
tci = ta.getBlocked(id_processor, block_wait);
wait = sWait;
} catch (SysException ex) {
Throwable ex1 = ex.getCause();
if (ex1 != null)
ex1.printStackTrace();
else
ex.printStackTrace();
try {
long prc_id = ta.getSubject(id_processor);
if (prc_id > 0 && prc_id != id_processor) {
ta.registerClasses(prc_id, hs.keySet());
id_processor = prc_id;
ATaskAPI.setApplicationSubject(ta, id_processor);
}
} catch (Throwable e) {
}
wait = sWait * 2;
try {
Thread.sleep(wait);
} catch (InterruptedException ex2) {
throw new SysException(ex2);
}
continue;
}
if (tci == null)
continue;
id_task = tci.id_task;
if (id_task == 0)
continue;
String classname_task = tci.cls_name;// ta.getClassName(id_task);
ta.log(id_processor, 0, "\tid = " + id_task, false);
ta.log(id_processor, 0, "\tclassname = " + classname_task, false);
TaskInfo ti = hs.get(classname_task);
if (ti == null) {
String err = "A compared processor for '" + classname_task
+ "' hasn't been found";
waiting = true;
do {
try {
ta.setTaskError(id_task, new SysException(err));
ta.setBroken(id_processor, id_task);
waiting = false;
} catch (SysException e) {
System.out.println("Waiting interface...");
Thread.sleep(1000);// TODO нужен параметр
}
} while (waiting);
continue;
}
AProcessor po = ti.newProcessorInstance();
ta.log(id_processor, id_task, "Processor = "
+ po.getClass().getCanonicalName(), false);
po.setPoolProcess(prcpool);
try {
po.start(prc, id_processor, id_task, ta, ti);
} catch (Throwable e) {
ta.setTaskError(id_task, e);
ta.setBroken(id_processor, id_task);
prcpool.free(prc);
} finally {
prc = null;
}
}
}
}