use of org.apache.activemq.artemis.core.server.HandleStatus in project activemq-artemis by apache.
the class QueueImpl method deliver.
/**
* This method will deliver as many messages as possible until all consumers are busy or there
* are no more matching or available messages.
*/
private void deliver() {
if (logger.isDebugEnabled()) {
logger.debug(this + " doing deliver. messageReferences=" + messageReferences.size());
}
doInternalPoll();
// Either the iterator is empty or the consumer is busy
int noDelivery = 0;
int size = 0;
int endPos = -1;
int handled = 0;
long timeout = System.currentTimeMillis() + DELIVERY_TIMEOUT;
while (true) {
if (handled == MAX_DELIVERIES_IN_LOOP) {
// Schedule another one - we do this to prevent a single thread getting caught up in this loop for too
// long
deliverAsync();
return;
}
if (System.currentTimeMillis() > timeout) {
if (logger.isTraceEnabled()) {
logger.trace("delivery has been running for too long. Scheduling another delivery task now");
}
deliverAsync();
return;
}
MessageReference ref;
Consumer handledconsumer = null;
synchronized (this) {
// Need to do these checks inside the synchronized
if (paused || consumerList.isEmpty()) {
return;
}
if (messageReferences.size() == 0) {
break;
}
if (endPos < 0 || consumersChanged) {
consumersChanged = false;
size = consumerList.size();
endPos = pos - 1;
if (endPos < 0) {
endPos = size - 1;
noDelivery = 0;
}
}
ConsumerHolder holder = consumerList.get(pos);
Consumer consumer = holder.consumer;
Consumer groupConsumer = null;
if (holder.iter == null) {
holder.iter = messageReferences.iterator();
}
if (holder.iter.hasNext()) {
ref = holder.iter.next();
} else {
ref = null;
}
if (ref == null) {
noDelivery++;
} else {
if (checkExpired(ref)) {
if (logger.isTraceEnabled()) {
logger.trace("Reference " + ref + " being expired");
}
holder.iter.remove();
refRemoved(ref);
handled++;
continue;
}
if (logger.isTraceEnabled()) {
logger.trace("Queue " + this.getName() + " is delivering reference " + ref);
}
// If a group id is set, then this overrides the consumer chosen round-robin
SimpleString groupID = extractGroupID(ref);
if (groupID != null) {
groupConsumer = groups.get(groupID);
if (groupConsumer != null) {
consumer = groupConsumer;
}
}
if (exclusive) {
consumer = consumerList.get(0).consumer;
}
HandleStatus status = handle(ref, consumer);
if (status == HandleStatus.HANDLED) {
deliveriesInTransit.countUp();
handledconsumer = consumer;
holder.iter.remove();
refRemoved(ref);
if (groupID != null && groupConsumer == null) {
groups.put(groupID, consumer);
}
handled++;
} else if (status == HandleStatus.BUSY) {
try {
holder.iter.repeat();
} catch (NoSuchElementException e) {
// this could happen if there was an exception on the queue handling
// and it returned BUSY because of that exception
//
// We will just log it as there's nothing else we can do now.
logger.warn(e.getMessage(), e);
}
noDelivery++;
} else if (status == HandleStatus.NO_MATCH) {
// nothing to be done on this case, the iterators will just jump next
}
}
if (pos == endPos) {
if (noDelivery == size) {
if (handledconsumer != null) {
// this shouldn't really happen,
// however I'm keeping this as an assertion case future developers ever change the logic here on this class
ActiveMQServerLogger.LOGGER.nonDeliveryHandled();
} else {
if (logger.isDebugEnabled()) {
logger.debug(this + "::All the consumers were busy, giving up now");
}
break;
}
}
noDelivery = 0;
}
// When using group we don't need to load balance to the next position
if (!exclusive && groupConsumer == null) {
pos++;
}
if (pos >= size) {
pos = 0;
}
}
if (handledconsumer != null) {
proceedDeliver(handledconsumer, ref);
}
}
checkDepage();
}
use of org.apache.activemq.artemis.core.server.HandleStatus in project activemq-artemis by apache.
the class QueueImpl method deliverDirect.
/*
* This method delivers the reference on the callers thread - this can give us better latency in the case there is nothing in the queue
*/
private boolean deliverDirect(final MessageReference ref) {
synchronized (this) {
if (!supportsDirectDeliver) {
// this would protect any eventual bug
return false;
}
if (paused || consumerList.isEmpty()) {
return false;
}
if (checkExpired(ref)) {
return true;
}
int startPos = pos;
int size = consumerList.size();
while (true) {
ConsumerHolder holder = consumerList.get(pos);
Consumer consumer = holder.consumer;
Consumer groupConsumer = null;
// If a group id is set, then this overrides the consumer chosen round-robin
SimpleString groupID = extractGroupID(ref);
if (groupID != null) {
groupConsumer = groups.get(groupID);
if (groupConsumer != null) {
consumer = groupConsumer;
}
}
if (exclusive) {
consumer = consumerList.get(0).consumer;
}
// Only move onto the next position if the consumer on the current position was used.
if (!exclusive && groupConsumer == null) {
pos++;
}
if (pos == size) {
pos = 0;
}
HandleStatus status = handle(ref, consumer);
if (status == HandleStatus.HANDLED) {
if (groupID != null && groupConsumer == null) {
groups.put(groupID, consumer);
}
messagesAdded.incrementAndGet();
deliveriesInTransit.countUp();
proceedDeliver(consumer, ref);
return true;
}
if (pos == startPos) {
// Tried them all
break;
}
}
return false;
}
}
Aggregations