Search in sources :

Example 1 with HandleStatus

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();
}
Also used : Consumer(org.apache.activemq.artemis.core.server.Consumer) HandleStatus(org.apache.activemq.artemis.core.server.HandleStatus) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) MessageReference(org.apache.activemq.artemis.core.server.MessageReference) NoSuchElementException(java.util.NoSuchElementException)

Example 2 with HandleStatus

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;
    }
}
Also used : Consumer(org.apache.activemq.artemis.core.server.Consumer) HandleStatus(org.apache.activemq.artemis.core.server.HandleStatus) SimpleString(org.apache.activemq.artemis.api.core.SimpleString)

Aggregations

SimpleString (org.apache.activemq.artemis.api.core.SimpleString)2 Consumer (org.apache.activemq.artemis.core.server.Consumer)2 HandleStatus (org.apache.activemq.artemis.core.server.HandleStatus)2 NoSuchElementException (java.util.NoSuchElementException)1 MessageReference (org.apache.activemq.artemis.core.server.MessageReference)1