All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.protocols.MFC_NB Maven / Gradle / Ivy

package org.jgroups.protocols;

import org.jgroups.Address;
import org.jgroups.Message;
import org.jgroups.annotations.MBean;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.Property;
import org.jgroups.conf.AttributeType;
import org.jgroups.util.CreditMap;
import org.jgroups.util.NonBlockingCreditMap;
import org.jgroups.util.Tuple;

import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;


/**
 * Non-blocking alternative to {@link MFC}.
* JIRA: JIRA: https://issues.redhat.com/browse/JGRP-2172 * @author Bela Ban * @since 4.0.4 */ @MBean(description="Simple non-blocking flow control protocol based on a credit system") public class MFC_NB extends MFC { @Property(description="Max number of bytes of all queued messages for a given destination. If a given destination " + "has no credits left and the message cannot be added to the queue because it is full, then the sender thread " + "will be blocked until there is again space available in the queue, or the protocol is stopped.",type=AttributeType.BYTES) protected int max_queue_size=10_000_000; protected final Consumer send_function=msg -> down_prot.down(msg); protected Future credit_send_task; public int getMaxQueueSize() {return max_queue_size;} public MFC_NB setMaxQueueSize(int s) {this.max_queue_size=s; return this;} @ManagedAttribute(description="Whether or not messages are currently being queued due to insufficient credits") public boolean isQueuing() { return ((NonBlockingCreditMap)credits).isQueuing(); } @ManagedAttribute(description="The number of messages currently queued due to insufficient credit" ,type=AttributeType.SCALAR) public int getNumberOfQueuedMessages() { return ((NonBlockingCreditMap)credits).getQueuedMessages(); } @ManagedAttribute(description="The total size of all currently queued messages",type=AttributeType.BYTES) public int getQueuedSize() { return ((NonBlockingCreditMap)credits).getQueuedMessageSize(); } @ManagedAttribute(description="The number of times messages have been queued due to insufficient credits" ,type=AttributeType.SCALAR) public int getNumberOfQueuings() { return ((NonBlockingCreditMap)credits).getEnqueuedMessages(); } protected CreditMap createCreditMap(long max_creds) { return new NonBlockingCreditMap(max_creds, max_queue_size, new ReentrantLock(true), send_function); } public void start() throws Exception { super.start(); if(max_block_time > 0) { credit_send_task=getTransport().getTimer() .scheduleWithFixedDelay(this::sendCreditRequestsIfNeeded, max_block_time, max_block_time, TimeUnit.MILLISECONDS); } } public void stop() { super.stop(); if(credit_send_task != null) credit_send_task.cancel(true); } @Override protected Object handleDownMessage(final Message msg, int length) { Address dest=msg.getDest(); if(dest != null) // 2nd line of defense, not really needed return down_prot.down(msg); if(running) { if(credits.decrement(msg, length, 0)) // timeout is ignored return down_prot.down(msg); // message was queued if(needToSendCreditRequest()) { List> targets=credits.getMembersWithCreditsLessThan(min_credits); for(Tuple tuple: targets) sendCreditRequest(tuple.getVal1(), Math.min(max_credits, max_credits - tuple.getVal2())); } return null; } return down_prot.down(msg); } /** * Checks the sent table: if some credits are in queueing mode and credits left are less than min_credits: * send a credit request */ protected void sendCreditRequestsIfNeeded() { if(credits.getMinCredits() < min_credits && needToSendCreditRequest()) { List> targets=credits.getMembersWithCreditsLessThan(min_credits); for(Tuple tuple: targets) sendCreditRequest(tuple.getVal1(), Math.min(max_credits, max_credits - tuple.getVal2())); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy