package cz.cuni.mff.d3s.been.socketworks.twoway;
import java.util.ArrayList;
import java.util.List;
import cz.cuni.mff.d3s.been.cluster.ServiceException;
import cz.cuni.mff.d3s.been.socketworks.Socketworks;
import org.jeromq.ZMQ;
import cz.cuni.mff.d3s.been.mq.Context;
import cz.cuni.mff.d3s.been.mq.MessagingException;
import cz.cuni.mff.d3s.been.mq.ZMQContext;
import cz.cuni.mff.d3s.been.socketworks.QueueGuard;
/**
* @author darklight
*/
class ReadReplyGuard implements QueueGuard {
private final String hostname;
private final PollPipeline pollPipeline;
private final ZMQContext zctx;
private final PipelineRouter router;
private final PipelineDealer dealer;
ReadReplyGuard(String hostname, PollPipeline pollPipeline, PipelineRouter pipelineRouter, PipelineDealer pipelineDealer, ZMQContext zctx) {
this.hostname = hostname;
this.pollPipeline = pollPipeline;
this.router = pipelineRouter;
this.dealer = pipelineDealer;
this.zctx = zctx;
}
public static
ReadReplyGuard
create(String hostname, ReadReplyHandlerFactory handlerFactory) throws MessagingException {
final ZMQContext zctx = Context.getReference();
final SkeletalFrameForwardMapper forwardMapper = new SkeletalFrameForwardMapper();
final PipelineRouter router = PipelineRouter.create(zctx.socket(ZMQ.ROUTER), hostname, forwardMapper);
final PipelineDealer dealer = PipelineDealer.create(zctx.socket(ZMQ.DEALER), hostname, forwardMapper);
final FrameSink handler = PipelineHandler.create(handlerFactory, forwardMapper);
// Bypass the 0MQ router/dealer model. Messages received on router get passed to handler.
// Handler spawns threads that handle content, then re-attaches IDs to responses.
// Crunched content then gets forwarded to dealer, who only provides de-multiplexing by reattaching IDs and forwarding back to the router to process sending.
forwardMapper.addRoute(router, handler);
forwardMapper.addRoute(handler, dealer);
forwardMapper.addRoute(dealer, router);
final List<PollPartaker> partakers = new ArrayList<PollPartaker>(2);
partakers.add(router);
partakers.add(dealer);
final PollPipeline pollPipeline = PollPipeline.create(partakers, forwardMapper);
return new ReadReplyGuard(hostname, pollPipeline, router, dealer, zctx);
}
@Override
public String getHostname() {
return hostname;
}
@Override
public Integer getPort() {
return router.getPort();
}
@Override
public String getConnection() {
return Socketworks.Protocol.TCP.connection(getHostname(), getPort());
}
@Override
public void listen() {
dealer.start();
router.start();
pollPipeline.start();
}
@Override
public void terminate() throws MessagingException {
pollPipeline.doStop();
try {
pollPipeline.join();
} catch (InterruptedException e) {
throw new MessagingException("Join on poll pipeline interrupted", e);
} finally {
router.stop();
dealer.stop();
zctx.term();
}
}
}