package ch.epfl.gsn.networking.zeromq;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import org.zeromq.ZMQ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeromq.ZContext;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import ch.epfl.gsn.DataDistributer;
import ch.epfl.gsn.Main;
import ch.epfl.gsn.Mappings;
import ch.epfl.gsn.beans.DataField;
import ch.epfl.gsn.delivery.DefaultDistributionRequest;
public class ZeroMQProxy extends Thread implements Runnable {
private static transient Logger logger = LoggerFactory.getLogger(ZeroMQProxy.class);
private ZContext ctx;
private ZMQ.Socket subscriberX;
private ZMQ.Socket publisherX;
private ZMQ.Socket clients;
private Kryo kryo = new Kryo();
private HashMap<String,DataField[]> structures = new HashMap<String,DataField[]>(); //maybe put into mappings...
public ZeroMQProxy (final int portOUT,final int portMETA){
kryo.register(DataField[].class);
ctx = Main.getZmqContext();
subscriberX = ctx.createSocket(ZMQ.XSUB);
publisherX = ctx.createSocket(ZMQ.XPUB);
publisherX.setXpubVerbose(true);
publisherX.setHWM(0);
subscriberX.setHWM(0);
publisherX.bind("tcp://*:"+portOUT);
clients = ctx.createSocket(ZMQ.REP);
clients.bind ("tcp://*:"+portMETA);
Thread dataProxy = new Thread(new Runnable(){
@Override
public void run() {
ZMQ.proxy(subscriberX, publisherX, null);
}
});
dataProxy.setName("ZMQ-PROXY-Thread");
dataProxy.start();
Thread metaResponder = new Thread(new Runnable(){
@Override
public void run() {
while (true) {
String request = clients.recvStr (0);
String [] parts = request.split("\\?");
if (parts.length > 1){
try{
long startTime = System.currentTimeMillis();
if (parts.length > 2){
startTime = Long.parseLong(parts[2]);
}
ZeroMQDeliverySync d = new ZeroMQDeliverySync(parts[0], parts[1]);
final DefaultDistributionRequest distributionReq = DefaultDistributionRequest.create(d, Mappings.getVSensorConfig(parts[0]), "select * from "+parts[0], startTime);
logger.info("ZMQ request received: "+distributionReq.toString());
DataDistributer.getInstance(d.getClass()).addListener(distributionReq);
}catch (Exception e){
logger.warn("ZMQ request parsing error: " + request, e);
}
}
byte[] b=new byte[0];
ByteArrayOutputStream bais = new ByteArrayOutputStream();
Output o = new Output(bais);
kryo.writeObjectOrNull(o,structures.get(parts[0]),DataField[].class);
o.close();
b = bais.toByteArray();
clients.send(b, 0);
}
}
});
metaResponder.setName("ZMQ-META-Thread");
metaResponder.start();
}
public void connectTo(String vsName){
subscriberX.connect("inproc://stream/"+vsName);
}
public void registerStructure(String name, DataField[] fields) {
structures.put(name, fields);
}
}