package center.app.common;
import center.task.*;
import center.task.api.ITaskAPI;
import ru.vassaev.core.CallBackInterface;
import ru.vassaev.core.Pool;
import ru.vassaev.core.PrmInterface;
import ru.vassaev.core.base.Null;
import ru.vassaev.core.container.ApplicationManager;
import ru.vassaev.core.io.ByteMsg;
import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.thread.*;
import ru.vassaev.core.thread.Process;
import ru.vassaev.core.thread.primitives.ServerSocketAcceptProcessed;
import ru.vassaev.core.thread.primitives.SocketReaderProcessed;
import ru.vassaev.core.util.Strings;
import java.util.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;
/**
*
*/
public class ByteMessageResponseProcessor extends AProcessor {
public ByteMessageResponseProcessor() {
}
private final Object sync = new Object();
// Пул потоков для обработки формирования задания
private String poolProcessName = null;
private PoolThread prcs = null;
private Pool<ByteMsg> poolmsg;
private Integer localport;
private int maxlink;
// private String host;
private String msg_grp_in = "in";
private String msg_grp_out = "out";
/**
* Чтение параметров и проверка параметров
*
* @param cntx - текущий контектс
* @throws SysException - в случае недостатка параметров или невалидных значений
*/
public void paramsValidateAndPrepare(Context cntx) throws SysException {
// Имя пула потоков исполнения
poolProcessName = cntx.getPrmString("process_pool");
if (Null.equ(poolProcessName))
throw new SysException("Parameter process_pool isn't set");
ru.vassaev.core.thread.Process prc = ru.vassaev.core.thread.Process
.currentProcess();
prcs = (PoolThread) ApplicationManager.getPoolByName(poolProcessName, Process.class);
// Определение пула контейнеров сообщений
String poolMessageName = cntx.getPrmString("message_pool");
if (Null.equ(poolMessageName))
throw new SysException("Parameter message_pool isn't set");
poolmsg = (Pool<ByteMsg>) ApplicationManager.getPoolByName(poolMessageName, ByteMsg.class);
localport = Strings.parseInteger(cntx.getPrmByFullName("localport"));
maxlink = Strings.parseIntegerNvl(cntx.getPrmByFullName("maxlink"), 50);
msg_grp_in = cntx.getPrmNvl("msg_grp_in", "in");
msg_grp_out = cntx.getPrmNvl("msg_grp_out", "out");
}
public State process(Context cntx) throws TaskException, SysException, InterruptedException {
paramsValidateAndPrepare(cntx);
// Инициализация сервера
ServerSocket ss = null;
State cur;
while (!State.BREAKING.equals(cur = cntx.ta.getState(cntx.id_task))) {
if (!cur.equals(State.PROCESSING))
throw new TaskException(State.DONE_ERR, "System error");
try {
ss = new ServerSocket(localport, maxlink);
break;
} catch (IOException e) {
e.printStackTrace();
synchronized (sync) {
sync.wait(1000);//TODO
}
}
}
if (State.BREAKING.equals(cur))
return State.BROKEN;
// Запуск процесса ожидания соединений
ServerSocketAcceptProcessed ssap = new ServerSocketAcceptProcessed(prcs, fSocketProcessed);
Process p = prcs.start_target("ServerSocket " + ss.getInetAddress().toString(), ssap, ss, null);
// Ожидание прерывания задания
while (!State.BREAKING.equals(cur = cntx.ta.getState(cntx.id_task))) {
if (!cur.equals(State.PROCESSING))
throw new TaskException(State.DONE_ERR, "System error");
synchronized (sync) {
sync.wait(1000);//TODO
}
}
// Завершение обработчика
p.willBreak();
p.interrupt();
return State.BROKEN;
}
private final Object sync_sock= new Object();
private final FactorySocketProcessed fSocketProcessed = new FactorySocketProcessed();
private class FactorySocketProcessed
implements CallBackInterface<Socket, Processed<Socket>> {
// Обработчик соединения
public Processed<Socket> callBack(Socket socket) {
SocketReaderProcessed<ByteMsg> sr = new SocketReaderProcessed<ByteMsg>(prcs, poolmsg, new FactoryMsgProcessed(socket));
return sr;
}
}
private class FactoryMsgProcessed
implements CallBackInterface<ByteMsg, Processed<ByteMsg>>
, Processed<ByteMsg> {
private Socket socket;
public FactoryMsgProcessed(Socket socket) {
super();
this.socket = socket;
}
public Processed<ByteMsg> callBack(ByteMsg prm) {
return FactoryMsgProcessed.this;
}
public void processing(ByteMsg prms) throws Throwable {
getContext().log(false, "Start processing message ", prms.getKey());
ITaskAPI ta = getTaskAPI();
long id_processor = getProcessorID();
Context child;
Context cntx = getContext();
Process cp = Process.currentProcess();
try {
cp.regResourceName(prms, "msg");
PrmInterface prm = prms.getPrmInterface();
ArrayList<String> flds = prm.getFieldNames();
for (String k : flds) {
String v = prm.getField(k);
cp.regResourceName(v, "msg." + k);
}
child = getChild().createAndReadyTask(ta, cntx, id_processor, msg_grp_in, prms);
if (child == null)
return;
long wait = Strings.parseIntegerNvl(cntx.getPrmString("wait"), 0);
if (wait == 0)
return;
State st = child.ta.waitFinished(child.id_subject, child.id_task, wait);
{
boolean need_reply;
try {
need_reply = Boolean.parseBoolean(Strings.getString(child.getPrmString("need_reply")));
} catch (Exception ex) {
need_reply = true;
}
if (!need_reply)
return;
Map<String, Object> prms_out = child.getGroupParams(msg_grp_out);
Iterator<Map.Entry<String, Object>> i = prms_out.entrySet().iterator();
prm = prms.getPrmInterface();
if (Strings.parseBooleanNvl(child.getPrmString("clear"), false))
prm.clearFields();
while (i.hasNext()) {
Map.Entry<String, Object> e = i.next();
Object o = e.getValue();
String[] fn = cntx.getFullName(e.getKey());
prm.setField(fn[1], Strings.getString(o));
}
synchronized(sync_sock) {
prms.sendTo(socket.getOutputStream());
}
}
} finally {
getContext().log(false, "End processing message ", prms.getKey());
}
}
}
public Set<String> dependentOn() {
Set<String> s = new HashSet<String>();
s.add("prm.process_pool");
s.add("prm.message_pool");
s.add("prm.localport");
s.add("prm.msg_grp_in");
s.add("prm.msg_grp_out");
return s;
}
public Set<String> loopDependentOn() {
Set<String> s = new HashSet<String>();
s.add("prm.wait");
s.add("child");
s.add("prm.child");
return s;
}
}