/** * CopyRight by Chinamobile * * Receiver.java */ package com.chinamobile.bcbsp.comm; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.chinamobile.bcbsp.api.Combiner; /** * Receiver * * A receiver belongs to a communicator, for receiving * messages and put them into the incoming queues. * * @author * @version */ public class Receiver extends Thread { // For log private static final Log LOG = LogFactory.getLog(Receiver.class); private Communicator communicator = null; //brokerName for this staff to receive messages. private String brokerName; private MessageQueuesInterface messageQueues = null; private int consumerNum = 1; private ArrayList<ConsumerTool> consumers = null; boolean combinerFlag = false; private Combiner combiner = null; private int combineThreshold = 3; private boolean noMoreMessagesFlag = false; private Long messageCount = 0L; public Receiver(Communicator comm, String brokerName) { this.communicator = comm; this.brokerName = brokerName; this.combinerFlag = this.communicator.isReceiveCombineSetFlag(); // Get the combiner from the communicator. if (combinerFlag) { this.combiner = this.communicator.getCombiner(); this.combineThreshold = this.communicator.getJob().getReceiveCombineThreshold(); } int usrProducerNum = this.communicator.getJob().getMaxProducerNum(); int usrConsumerNum = this.communicator.getJob().getMaxConsumerNum(); if (usrConsumerNum <= usrProducerNum) { this.consumerNum = usrConsumerNum; } this.consumers = new ArrayList<ConsumerTool>(); } public void addMessageCount(long count) { synchronized (this.messageCount) { this.messageCount += count; } } public void run() { try { LOG.info("[Receiver] starts successfully!"); LOG.info("========== Initialize Receiver =========="); if (this.combinerFlag) { LOG.info("[Combine Threshold for receiving] = " + this.combineThreshold); } else { LOG.info("No combiner or combiner turned off for receiving!!!"); } LOG.info("[Consumer Number] = " + this.consumerNum); LOG.info("========================================="); this.messageQueues = this.communicator.getMessageQueues(); ConsumerTool consumer = null; for (int i = 0; i < this.consumerNum; i ++) { consumer = new ConsumerTool(this, this.messageQueues, this.brokerName, "BSP"); consumer.start(); // Start the consumer. this.consumers.add(consumer); } int maxSize = 0; String incomingIndex = null; ConcurrentLinkedQueue<BSPMessage> maxQueue = null; while (true) { // Wait until the consumerTool has finished, the Receiver // will finish. if (combinerFlag) { maxSize = 0; maxQueue = null; incomingIndex = this.messageQueues.getMaxIncomingQueueIndex(); if (incomingIndex != null) { maxSize = this.messageQueues.getIncomingQueueSize(incomingIndex); } // When the longest queue's length reaches the threshold if (maxSize >= combineThreshold) { // Get the queue out of the map. maxQueue = this.messageQueues.removeIncomingQueue(incomingIndex); // Combine the max queue into just one message. BSPMessage message = combine(maxQueue); this.messageQueues.incomeAMessage(incomingIndex, message); } } else { try { // For no combiner define, just sleep for next check. Thread.sleep(1000); } catch (InterruptedException e) { LOG.error("[Receiver] caught", e); } } Iterator<ConsumerTool> itr = consumers.iterator(); int running = 0; while (itr.hasNext()) { ConsumerTool thread = itr.next(); if (thread.isAlive()) { running++; } } if (running <= 0) { //All consumers are finished. break; } } LOG.info("[Receiver] has received " + this.messageCount + " BSPMessages totally!"); LOG.info("[Receiver] exits."); } catch (Exception e) { LOG.error("[Receiver] caught: ", e); } } /** * To tell the consumer tool that there are no * more messages for it. * * @param flag */ public void setNoMoreMessagesFlag(boolean flag) { this.noMoreMessagesFlag = flag; } public boolean getNoMoreMessagesFlag() { return this.noMoreMessagesFlag; } public void setCombineThreshold(int aCombineThreshold) { if (this.combineThreshold == 0) { this.combineThreshold = aCombineThreshold; } } private BSPMessage combine(ConcurrentLinkedQueue<BSPMessage> incomingQueue) { BSPMessage msg = this.combiner.combine(incomingQueue.iterator()); return msg; } }