package org.jgroups.util; import org.jgroups.Address; import org.jgroups.Message; import org.jgroups.logging.Log; import org.jgroups.protocols.MsgStats; import org.jgroups.protocols.TP; import org.jgroups.protocols.TpHeader; import org.jgroups.stack.MessageProcessingPolicy; import java.util.Iterator; /** * Default message processing policy. Submits all received messages and batches to the thread pool * @author Bela Ban * @since 4.0 */ public class SubmitToThreadPool implements MessageProcessingPolicy { protected TP tp; protected short tp_id; protected Log log; public void init(TP transport) { this.tp=transport; this.tp_id=tp.getId(); this.log=tp.getLog(); } public void loopback(Message msg, boolean oob, boolean internal) { tp.submitToThreadPool(() -> tp.passMessageUp(msg, null, false, msg.dest() == null,false), internal); } public void process(Message msg, boolean oob, boolean internal) { tp.submitToThreadPool(new SingleMessageHandler(msg), internal); } public void process(MessageBatch batch, boolean oob, boolean internal) { if(oob) removeAndDispatchNonBundledMessages(batch); tp.submitToThreadPool(new BatchHandler(batch), internal); } /** * Removes messages with flags DONT_BUNDLE and OOB set and executes them in the oob or internal thread pool. JGRP-1737 */ protected void removeAndDispatchNonBundledMessages(MessageBatch oob_batch) { if(oob_batch == null) return; AsciiString tmp=oob_batch.clusterName(); byte[] cname=tmp != null? tmp.chars() : null; for(Iterator<Message> it=oob_batch.iterator(); it.hasNext();) { Message msg=it.next(); if(msg.isFlagSet(Message.Flag.DONT_BUNDLE) && msg.isFlagSet(Message.Flag.OOB)) { boolean internal=msg.isFlagSet(Message.Flag.INTERNAL); it.remove(); if(tp.statsEnabled()) tp.getMessageStats().incrNumOOBMsgsReceived(1); tp.submitToThreadPool(new SingleMessageHandlerWithClusterName(msg, cname), internal); } } } protected class SingleMessageHandler implements Runnable { protected final Message msg; protected SingleMessageHandler(final Message msg) { this.msg=msg; } public void run() { Address dest=msg.getDest(); boolean multicast=dest == null; try { if(tp.statsEnabled()) { MsgStats msg_stats=tp.getMessageStats(); if(msg.isFlagSet(Message.Flag.OOB)) msg_stats.incrNumOOBMsgsReceived(1); else if(msg.isFlagSet(Message.Flag.INTERNAL)) msg_stats.incrNumInternalMsgsReceived(1); else msg_stats.incrNumMsgsReceived(1); msg_stats.incrNumBytesReceived(msg.getLength()); } byte[] cname=getClusterName(); tp.passMessageUp(msg, cname, true, multicast, true); } catch(Throwable t) { log.error(Util.getMessage("PassUpFailure"), t); } } protected byte[] getClusterName() { TpHeader hdr=msg.getHeader(tp_id); return hdr.getClusterName(); } } protected class SingleMessageHandlerWithClusterName extends SingleMessageHandler { protected final byte[] cluster; @Override protected byte[] getClusterName() { return cluster; } protected SingleMessageHandlerWithClusterName(Message msg, byte[] cluster_name) { super(msg); this.cluster=cluster_name; } } protected class BatchHandler implements Runnable { protected MessageBatch batch; public BatchHandler(final MessageBatch batch) { this.batch=batch; } public void run() { if(batch == null || (!batch.multicast() && tp.unicastDestMismatch(batch.dest()))) return; if(tp.statsEnabled()) { int batch_size=batch.size(); MsgStats msg_stats=tp.getMessageStats(); if(batch.getMode() == MessageBatch.Mode.OOB) msg_stats.incrNumOOBMsgsReceived(batch_size); else if(batch.getMode() == MessageBatch.Mode.INTERNAL) msg_stats.incrNumInternalMsgsReceived(batch_size); else msg_stats.incrNumMsgsReceived(batch_size); msg_stats.incrNumBatchesReceived(1); msg_stats.incrNumBytesReceived(batch.length()); tp.avgBatchSize().add(batch_size); } passBatchUp(); } protected void passBatchUp() { tp.passBatchUp(batch, true, true); } } }