package center.app.common;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
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.exception.SysException;
import ru.vassaev.core.exception.SysRuntimeException;
import ru.vassaev.core.io.ByteMsg;
import ru.vassaev.core.thread.Process;
import ru.vassaev.core.thread.Processed;
import ru.vassaev.core.types.StringList;
import ru.vassaev.core.util.Sockets;
import ru.vassaev.core.util.Strings;
import center.task.*;
import center.task.api.ITaskAPI;
/**
* Обработка запроса по протоколу ByteMsg
* Общая схема работы:
* - Открывается порт на прием сообщения
* - После приема сообщения в отдельном потоке:
* - Создается задание Child с копированием параметров в группу
* , заданную параметром [msg_grp_in] (по умолчанию in)
* - Ожидается завершение задания Child
* - Результат отсылается в том же соединении.
* Параметры набираются из группы, заданной параметром [msg_grp_out] (по умолчанию out)
* @author Vassaev A.V.
* @version 1.0
*/
public class ByteMsgResponseProcessor extends AProcessor {
private Pool<ByteMsg> poolmsg = null;
private enum Type {
CLIENT, SERVER
}
private Type type;
public ByteMsg getMsg() {
try {
return poolmsg.occupyWait();
} catch (SysRuntimeException e) {
return null;
}
}
public void freeMsg(ByteMsg m) {
if (m != null) {
m.reset();
poolmsg.free(m);
}
}
// Пул потоков для обработки формирования задания
private String poolProcessName = null;
private Pool<ru.vassaev.core.thread.Process> prcs = null;
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 = (Pool<Process>) ApplicationManager.getPoolByName(poolProcessName, Process.class);
// Тип соединения tcp/ip (CLIENT / SERVER)
String type_str = Strings.getString(cntx.getPrmByFullName("type"),
"CLIENT");
type = Type.valueOf(type_str);
// Определение пула контейнеров сообщений
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"));
if (Type.CLIENT.equals(type)) {
host = cntx.getPrmString("host");
if (Null.equ(host))
throw new SysException("Parameter by name \"host\" isn't set");
} else {
if (Null.equ(localport))
throw new SysException("Parameter by name \"localport\" isn't set");
maxlink = Strings.parseIntegerNvl(cntx.getPrmByFullName("maxlink"), 50);
}
msg_grp_in = cntx.getPrmString("msg_grp_in");
if (msg_grp_in == null)
msg_grp_in = "in";
msg_grp_out = cntx.getPrmString("msg_grp_out");
if (msg_grp_out == null)
msg_grp_out = "out";
}
private class Finish implements CallBackInterface<Process, Object> {
public Object callBack(Process prc) {
prcs.free(prc);
return null;
}
}
private Finish finish = new Finish();
private ServerSocket ss;
private void init_server() throws IOException {
ss = new ServerSocket(localport, maxlink);
}
private void init_client() {
}
public ByteMsgResponseProcessor() {
}
private class Target implements Processed<Socket>,
CallBackInterface<Object[], ByteMsg> {
private String nameLink;
private InputStream is = null;
private OutputStream os = null;
private synchronized void sendMsg(ByteMsg m) throws IOException {
m.sendTo(os);
}
public void processing(Socket s) throws Throwable {
nameLink = Sockets.getNameLink(s);
try {
System.out.println("Started link " + nameLink);
is = s.getInputStream();
os = s.getOutputStream();
ByteMsg.processRead(is, this);
} finally {
}
}
public ByteMsg callBack(Object[] objs) {
if (!Null.equ(objs) && objs.length > 1) {
ByteMsg msg = (ByteMsg)objs[1];
if (ByteMsg.ACTION.FREE.equals(objs[0])) {
freeMsg(msg);
System.out.println("Dropped link " + nameLink);
try {
os.close();
} catch (IOException e) {
}
try {
is.close();
} catch (IOException e) {
}
return null;
}
//System.out.println("Recived message:");
PrmInterface prm;
/*
try {
prm = msg.getPrmInterface();
StringList names = prm.getFieldNames();
for (int j = 0; j < names.size(); j++) {
System.out.println("\t" + names.get(j) + " = " + prm.getField(names.get(j)));
}
} catch (SysException e1) {
e1.printStackTrace();
}
*/
Process tr;
// Создать поток обработки
tr = prcs.occupy();
// старт обработки;
try {
SingleProccesor target = new SingleProccesor(msg, this);
tr.setTarget(target);
tr.start();
} catch (RuntimeException e) {
prcs.free(tr);
freeMsg(msg);
e.printStackTrace();
} catch (SysException e) {
prcs.free(tr);
freeMsg(msg);
e.printStackTrace();
}
}
// Получить новый буфер для приёма
return getMsg();
}
}
private void process_server() throws IOException {
while (true) {
Socket s = ss.accept();
Process prc = prcs.occupy();
prc.setCallBackOnEndProcess(finish);
System.out.println("Created link " + Sockets.getNameLink(s));
prc.setTarget(new Target());
prc.start(s);
}
}
private void process_client() throws UnknownHostException, IOException {
Socket s = new Socket(host, localport);
System.out.println("++++3+++PRCPOOL.BusySize = " + prcs.getBusySize());
Process prc = prcs.occupy();
prc.setCallBackOnEndProcess(finish);
System.out.println("Created link " + Sockets.getNameLink(s));
prc.setTarget(new Target());
prc.start(s);
}
public State process(Context cntx) throws SysException, TaskException {
paramsValidateAndPrepare(cntx);
try {
if (type.equals(Type.SERVER)) {
init_server();
process_server();
} else {
init_client();
process_client();
}
} catch (IOException e) {
throw new TaskException(State.DONE_ERR, e);
}
Object sync = new Object();
while (true) {
try {
sync.wait(10000);// !!!Нужен параметр
} catch (InterruptedException e) {
break;
}
}
return State.BROKEN;
}
private class SingleProccesor implements Processed {
private ByteMsg in;
private long id_task;
private ITaskAPI ta;
private NewTaskInfo child;
private boolean need_reply = true;
private Target tprcs;
public SingleProccesor(ByteMsg in, Target prcs) throws SysException {
super();
init(in, prcs);
}
public void init(ByteMsg in, Target prcs) throws SysException {
this.in = in;
this.tprcs = prcs;
ta = getTaskAPI();
id_task = getTaskID();
child = getChild();
}
public void processing(Object oprm) {
PrmInterface prm;
try {
long id_processor = getProcessorID();
prm = in.getPrmInterface();
ArrayList<String> flds = prm.getFieldNames();
for (String k : flds) {
String v = prm.getField(k);
Process.currentProcess().regResourceName(v, "msg." + k);
}
Context cntx = getContext();
// Создать и подготовить для выполнения дочернюю задачу
Context chld = child
.createAndReadyTask(ta, cntx, id_processor, msg_grp_in, prm);
need_reply = Strings.parseBooleanNvl(chld.getPrmByFullName("need_reply"), false);
try {
long wait = Strings.parseIntegerNvl(chld.getPrmByFullName("wait"), 120000);
cntx.log(false, "Start waiting (", wait, ")");
State r = chld.ta.waitFinished(chld.id_subject, chld.id_task, wait);
cntx.log(false, "End waiting");
need_reply = Strings.parseBooleanNvl(chld.getPrmByFullName("need_reply"), true);
Map<String, Object> prms_out = chld.getGroupParams(msg_grp_out);
Iterator<String> i = prms_out.keySet().iterator();
prm = in.getPrmInterface();
if ("true".equalsIgnoreCase(Strings.getString(chld.getPrmByFullName("clear"))))
prm.clearFields();
while (i.hasNext()) {
String n = i.next();
String[] fn = Context.getFullName(n);
String o = Strings.getString(prms_out.get(n));
//System.out.println("\t set " + n + " = " + o);
prm.setField(fn[1], o);
// ((ISO8583Msg)in).printStatusHeader();
}
} catch (SysException ex1) {
ta.setTaskError(chld.id_task, ex1);
chld.log(false, "The task was completed with errors");
chld.log(false, ex1.getMessage());
ta.setDoneErr(id_processor, chld.id_task);
} finally {
try {
if (need_reply)
tprcs.sendMsg(in);
chld.log(false, "NEED_REPLY = ", need_reply);
} catch (IOException ex1) {
ta.setTaskError(chld.id_task, ex1);
chld.log(false, "The task was completed with errors");
chld.log(false, ex1.getMessage());
ta.setDoneErr(id_processor, chld.id_task);
}
freeMsg(in);
}
} catch (SysException ex) {
throw new RuntimeException(ex);
} finally {
freeMsg(in);
prcs.free(Process.currentProcess());
}
}
}
public Set<String> dependentOn() {
Set<String> s = new HashSet<String>();
return s;
}
public Set<String> loopDependentOn() {
Set<String> s = new HashSet<String>();
return s;
}
}