package cz.cuni.mff.d3s.been.socketworks.oneway; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cz.cuni.mff.d3s.been.mq.IMessageReceiver; import cz.cuni.mff.d3s.been.mq.IMessageSender; import cz.cuni.mff.d3s.been.mq.MessageQueues; import cz.cuni.mff.d3s.been.mq.MessagingException; import cz.cuni.mff.d3s.been.socketworks.QueueGuard; import java.net.URI; import java.net.URL; /** * Keeper object for a read-only message queue and its listener thread. * * @author darklight */ class ReadOnlyGuard implements QueueGuard { private static final Logger log = LoggerFactory.getLogger(ReadOnlyGuard.class); /** * THIS MESSAGE STRING IS FOR PRIVATE USE ONLY. Its purpose is to poison * listener threads to signal them to stop listening. */ static final String STOP_MESSAGE = "XX1456123_STOP_RECEIVER_MESSAGE"; private final String hostname; private final String queueName; private final ReadOnlyListener listener; private final IMessageReceiver<String> receiver; private ReadOnlyGuard(String hostname, String queueName, IMessageReceiver<String> receiver, ReadOnlyHandler handler) { this.hostname = hostname; this.queueName = queueName; this.receiver = receiver; this.listener = ReadOnlyListener.create(receiver, handler); } public static ReadOnlyGuard create(String hostname, String qName, ReadOnlyHandler handler) throws MessagingException { final IMessageReceiver<String> receiver = MessageQueues.getInstance().createTcpQueue(qName, hostname).getReceiver(); return new ReadOnlyGuard(hostname, qName, receiver, handler); } @Override public String getHostname() { return hostname; } @Override public Integer getPort() { return receiver.getPort(); } @Override public String getConnection() { return String.format("tcp://%s:%d", getHostname(), getPort()); } @Override public void listen() { listener.start(); } @Override public void terminate() throws MessagingException { poisonReader(); MessageQueues.getInstance().terminate(queueName); } private void poisonReader() throws MessagingException { IMessageSender<String> sender = MessageQueues.getInstance().createSender(queueName); try { sender.send(STOP_MESSAGE); } finally { sender.close(); } try { listener.join(); } catch (InterruptedException e) { log.warn("Poisoner thread interrupted", e); } } }