use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class QueueImplTest method testMessagesAdded.
@Test
public void testMessagesAdded() throws Exception {
QueueImpl queue = getTemporaryQueue();
MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3);
queue.addTail(messageReference);
queue.addTail(messageReference2);
queue.addTail(messageReference3);
Assert.assertEquals(getMessagesAdded(queue), 3);
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class PostOfficeJournalLoader method handleAddMessage.
@Override
public void handleAddMessage(Map<Long, Map<Long, AddMessageRecord>> queueMap) throws Exception {
for (Map.Entry<Long, Map<Long, AddMessageRecord>> entry : queueMap.entrySet()) {
long queueID = entry.getKey();
Map<Long, AddMessageRecord> queueRecords = entry.getValue();
Queue queue = this.queues.get(queueID);
if (queue == null) {
if (queueRecords.values().size() != 0) {
ActiveMQServerLogger.LOGGER.journalCannotFindQueueForMessage(queueID);
}
continue;
}
// Redistribution could install a Redistributor while we are still loading records, what will be an issue with
// prepared ACKs
// We make sure te Queue is paused before we reroute values.
queue.pause();
Collection<AddMessageRecord> valueRecords = queueRecords.values();
long currentTime = System.currentTimeMillis();
for (AddMessageRecord record : valueRecords) {
long scheduledDeliveryTime = record.getScheduledDeliveryTime();
if (scheduledDeliveryTime != 0 && scheduledDeliveryTime <= currentTime) {
scheduledDeliveryTime = 0;
record.getMessage().setScheduledDeliveryTime(0L);
}
if (scheduledDeliveryTime != 0) {
record.getMessage().setScheduledDeliveryTime(scheduledDeliveryTime);
}
MessageReference ref = postOffice.reroute(record.getMessage(), queue, null);
ref.setDeliveryCount(record.getDeliveryCount());
if (scheduledDeliveryTime != 0) {
record.getMessage().setScheduledDeliveryTime(0L);
}
}
}
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class QueueImpl method purgeAfterRollback.
private void purgeAfterRollback(LinkedList<MessageReference> refs) {
try {
Transaction transaction = new TransactionImpl(storageManager);
for (MessageReference reference : refs) {
// post ack will decrement this, so need to inc
incDelivering(reference);
acknowledge(transaction, reference, AckReason.KILLED);
}
transaction.commit();
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class QueueImpl method removeReferenceWithID.
@Override
public synchronized MessageReference removeReferenceWithID(final long id1) throws Exception {
try (LinkedListIterator<MessageReference> iterator = iterator()) {
MessageReference removed = null;
while (iterator.hasNext()) {
MessageReference ref = iterator.next();
if (ref.getMessage().getMessageID() == id1) {
iterator.remove();
refRemoved(ref);
removed = ref;
break;
}
}
if (removed == null) {
// Look in scheduled deliveries
removed = scheduledDeliveryHandler.removeReferenceWithID(id1);
}
return removed;
}
}
use of org.apache.activemq.artemis.core.server.MessageReference 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();
}
Aggregations