Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jgroups.util;
import org.jgroups.BaseMessage;
import org.jgroups.Message;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
/**
* Non-blocking credit for a unicast destination.
* Instead of blocking when insufficient credits are available for sending a message, this class queues the
* message and sends it at a later time when enough credits have been received to send it.
* JIRA: https://issues.redhat.com/browse/JGRP-2172
* @author Bela Ban
* @since 4.0.4
*/
public class NonBlockingCredit extends Credit {
protected final SizeBoundedQueue msg_queue;
protected boolean queuing; // messages will be queued when true
protected final Consumer send_function;
protected static final Consumer NO_OP_SEND_FUNCTION=msg -> {};
protected final LongAdder num_queued=new LongAdder();
public NonBlockingCredit(long credits, int max_size, Lock lock) {
this(credits, max_size, lock, NO_OP_SEND_FUNCTION);
}
public NonBlockingCredit(long credits, int max_size, Lock lock, final Consumer send_function) {
super(credits, lock);
this.msg_queue=new SizeBoundedQueue<>(max_size, lock);
this.send_function=send_function;
}
public boolean isQueuing() {return queuing;}
public int getQueuedMessages() {return msg_queue.getElements();}
public int getQueuedMessageSize() {return msg_queue.size();}
public int getEnqueuedMessages() {return num_queued.intValue();}
public void resetStats() {
super.resetStats();
num_queued.reset();
}
/**
* Decrements the sender's credits by the size of the message.
* @param msg The message
* @param credits The number of bytes to decrement the credits. Is {@link BaseMessage#getLength()}.
* @param timeout Ignored
* @return True if the message was sent, false if it was queued
*/
public boolean decrementIfEnoughCredits(final Message msg, int credits, long timeout) {
lock.lock();
try {
if(done)
return false;
if(queuing)
return addToQueue(msg, credits);
if(decrement(credits))
return true; // enough credits, message will be sent
queuing=true; // not enough credits, start queuing
return addToQueue(msg, credits);
}
finally {
lock.unlock();
}
}
public void increment(long credits, long max_credits) {
List drain_list;
lock.lock();
try {
super.increment(credits, max_credits);
if(!queuing || msg_queue.isEmpty())
return;
int drained=msg_queue.drainTo(drain_list=new ArrayList<>(msg_queue.getElements()), (int)this.credits_left);
if(drained > 0)
credits_left=Math.min(max_credits, credits_left - drained);
if(msg_queue.isEmpty())
queuing=false;
}
finally {
lock.unlock();
}
// finally send drained messages:
if(!drain_list.isEmpty())
drain_list.forEach(send_function);
}
public Credit reset() {
lock.lock();
try {
super.reset();
queuing=false;
msg_queue.clear(true);
return this;
}
finally {
lock.unlock();
}
}
public String toString() {
return String.format("%s bytes left (queuing: %b, msg-queue size: %d, bytes: %s, enqueued: %d)",
super.toString(), isQueuing(), getQueuedMessages(), Util.printBytes(getQueuedMessageSize()), num_queued.intValue());
}
protected boolean addToQueue(Message msg, int length) {
try {
msg_queue.add(msg, length);
num_queued.increment();
}
catch(InterruptedException e) {
}
return false;
}
}