package com.joelpm.bidiMessages.server; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.apache.log4j.Logger; import org.apache.thrift.TException; import com.joelpm.bidiMessages.generated.Message; import com.joelpm.bidiMessages.generated.MessageService.Iface; /** * A simple class that uses a blocking queue to accept and publish * messages. This class should be run in its own thread to ensure * that message sending doesn't hijack the message receiving thread. * * @author Joel Meyer */ public class MessageDistributor implements Iface, Runnable { private static final Logger LOGGER = Logger.getLogger(MessageDistributor.class); private final BlockingQueue<Message> messageQueue; private final List<MessageServiceClient> clients; public MessageDistributor() { this.messageQueue = new LinkedBlockingQueue<Message>(); this.clients = new ArrayList<MessageServiceClient>(); } public void addClient(MessageServiceClient client) { // There should be some synchronization around this list clients.add(client); LOGGER.info(String.format("Added client at %s", client.getAddy())); } @Override public void run() { while (true) { try { Message msg = messageQueue.take(); Iterator<MessageServiceClient> clientItr = clients.iterator(); while (clientItr.hasNext()) { MessageServiceClient client = clientItr.next(); try { client.sendMessage(msg); } catch (TException te) { // Most likely client disconnected, should remove it from the list clientItr.remove(); LOGGER.info(String.format("Removing %s from client list.", client.getAddy())); LOGGER.debug(te); } } } catch (InterruptedException ie) { LOGGER.debug(ie); } } } @Override public void sendMessage(Message msg) throws TException { messageQueue.add(msg); LOGGER.info(String.format("Adding message to queue:\n%s", msg)); } }