com.chinamobile.bcbsp.comm.Receiver.java Source code

Java tutorial

Introduction

Here is the source code for com.chinamobile.bcbsp.comm.Receiver.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.chinamobile.bcbsp.comm;

import com.chinamobile.bcbsp.api.Combiner;

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;

/**
 * A receiver belongs to a communicator, for receiving messages and put them
 * into the incoming queues.
 */
public class Receiver extends Thread {
    /** class logger. */
    private static final Log LOG = LogFactory.getLog(Receiver.class);
    /** The communication tool for BSP. */
    private Communicator communicator = null;
    /** brokerName for this staff to receive messages. */
    private String brokerName;
    /** message Queues. */
    private MessageQueuesInterface messageQueues = null;
    /** the number of consumer. */
    private int consumerNum = 1;
    /** List of consumers. */
    private ArrayList<ConsumerTool> consumers = null;
    /** flag of combiner. */
    private boolean combinerFlag = false;
    /** combiner of receiver. */
    private Combiner combiner = null;
    /** combine threshold default is 3. */
    private int combineThreshold = 3;
    /** flag of no more messages. */
    private boolean noMoreMessagesFlag = false;
    /** message counter. */
    private Long messageCount = 0L;
    /** message bytes counter. */
    // add by chen
    private Long messageBytesCount = 0L;

    /**
     * Constructor of Receiver.
     * @param comm
     * @param brokerName
     */
    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>();
    }

    /**Message counter add 1.*/
    public void addMessageCount(long count) {
        synchronized (this.messageCount) {
            this.messageCount += count;
        }
    }

    /**Add message bytes counter.*/
    public void addMessageBytesCount(Long messageBytesCount) {
        this.messageBytesCount += messageBytesCount;
    }

    /**Run method of Thread.*/
    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<IMessage> maxQueue = null;
            // Wait until the consumerTool has finished, the Receiver will finish.
            while (true) {
                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.
                        IMessage 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;
                }
            }
            this.communicator.setReceivedMessageCounter(this.messageCount);
            this.communicator.setReceivedMessageBytesCounter(this.messageBytesCount);
            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;
    }

    /**Flag of noMoreMessagesFlag.*/
    public boolean getNoMoreMessagesFlag() {
        return this.noMoreMessagesFlag;
    }

    /**Set method of combineThreshold.*/
    public void setCombineThreshold(int aCombineThreshold) {
        if (this.combineThreshold == 0) {
            this.combineThreshold = aCombineThreshold;
        }
    }

    /**
     * Combine the incoming message queue.
     * @return IMessage
     */
    @SuppressWarnings("unchecked")
    private IMessage combine(ConcurrentLinkedQueue<IMessage> incomingQueue) {
        IMessage msg = (IMessage) this.combiner.combine(incomingQueue.iterator());
        return msg;
    }

    /** For JUnit test. */
    public boolean isCombinerFlag() {
        return combinerFlag;
    }

    public Long getMessageCount() {
        return messageCount;
    }

    public Long getMessageBytesCount() {
        return messageBytesCount;
    }
}