use of org.apache.activemq.artemis.core.server.Consumer in project activemq-artemis by apache.
the class QueueControlImpl method listConsumersAsJSON.
@Override
public String listConsumersAsJSON() throws Exception {
checkStarted();
clearIO();
try {
Collection<Consumer> consumers = queue.getConsumers();
JsonArrayBuilder jsonArray = JsonLoader.createArrayBuilder();
for (Consumer consumer : consumers) {
if (consumer instanceof ServerConsumer) {
ServerConsumer serverConsumer = (ServerConsumer) consumer;
JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("consumerID", serverConsumer.getID()).add("connectionID", serverConsumer.getConnectionID().toString()).add("sessionID", serverConsumer.getSessionID()).add("browseOnly", serverConsumer.isBrowseOnly()).add("creationTime", serverConsumer.getCreationTime());
jsonArray.add(obj);
}
}
return jsonArray.build().toString();
} finally {
blockOnIO();
}
}
use of org.apache.activemq.artemis.core.server.Consumer in project activemq-artemis by apache.
the class ConsumerWindowSizeTest method testNoWindowRoundRobin.
private void testNoWindowRoundRobin(final boolean largeMessages) throws Exception {
ActiveMQServer server = createServer(false, isNetty());
ClientSession sessionA = null;
ClientSession sessionB = null;
try {
final int numberOfMessages = 100;
server.start();
locator.setConsumerWindowSize(-1);
if (largeMessages) {
locator.setMinLargeMessageSize(100);
}
ClientSessionFactory sf = createSessionFactory(locator);
sessionA = sf.createSession(false, true, true);
SimpleString ADDRESS = new SimpleString("some-queue");
sessionA.createQueue(ADDRESS, ADDRESS, true);
sessionB = sf.createSession(false, true, true);
sessionA.start();
sessionB.start();
ClientConsumerInternal consA = (ClientConsumerInternal) sessionA.createConsumer(ADDRESS);
ClientConsumerInternal consB = (ClientConsumerInternal) sessionB.createConsumer(ADDRESS);
{
// We can only guarantee round robing with WindowSize = -1, after the ServerConsumer object received
// SessionConsumerFlowCreditMessage(-1)
// Since that is done asynchronously we verify that the information was received before we proceed on
// sending messages or else the distribution won't be
// even as expected by the test
Bindings bindings = server.getPostOffice().getBindingsForAddress(ADDRESS);
Assert.assertEquals(1, bindings.getBindings().size());
for (Binding binding : bindings.getBindings()) {
Collection<Consumer> consumers = ((QueueBinding) binding).getQueue().getConsumers();
for (Consumer consumer : consumers) {
ServerConsumerImpl consumerImpl = (ServerConsumerImpl) consumer;
long timeout = System.currentTimeMillis() + 5000;
while (timeout > System.currentTimeMillis() && consumerImpl.getAvailableCredits() != null) {
Thread.sleep(10);
}
Assert.assertNull(consumerImpl.getAvailableCredits());
}
}
}
ClientProducer prod = sessionA.createProducer(ADDRESS);
for (int i = 0; i < numberOfMessages; i++) {
ClientMessage msg = createTextMessage(sessionA, "Msg" + i);
if (largeMessages) {
msg.getBodyBuffer().writeBytes(new byte[600]);
}
prod.send(msg);
}
long timeout = System.currentTimeMillis() + TIMEOUT * 1000;
boolean foundA = false;
boolean foundB = false;
do {
foundA = consA.getBufferSize() == numberOfMessages / 2;
foundB = consB.getBufferSize() == numberOfMessages / 2;
Thread.sleep(10);
} while ((!foundA || !foundB) && System.currentTimeMillis() < timeout);
Assert.assertTrue("ConsumerA didn't receive the expected number of messages on buffer (consA=" + consA.getBufferSize() + ", consB=" + consB.getBufferSize() + ") foundA = " + foundA + " foundB = " + foundB, foundA);
Assert.assertTrue("ConsumerB didn't receive the expected number of messages on buffer (consA=" + consA.getBufferSize() + ", consB=" + consB.getBufferSize() + ") foundA = " + foundA + " foundB = " + foundB, foundB);
} finally {
try {
if (sessionA != null) {
sessionA.close();
}
if (sessionB != null) {
sessionB.close();
}
} catch (Exception ignored) {
}
}
}
use of org.apache.activemq.artemis.core.server.Consumer 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.Consumer 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;
}
}
use of org.apache.activemq.artemis.core.server.Consumer in project activemq-artemis by apache.
the class ActiveMQServerControlImpl method closeConsumerConnectionsForAddress.
@Override
public boolean closeConsumerConnectionsForAddress(final String address) {
boolean closed = false;
checkStarted();
clearIO();
try {
for (Binding binding : postOffice.getMatchingBindings(SimpleString.toSimpleString(address)).getBindings()) {
if (binding instanceof LocalQueueBinding) {
Queue queue = ((LocalQueueBinding) binding).getQueue();
for (Consumer consumer : queue.getConsumers()) {
if (consumer instanceof ServerConsumer) {
ServerConsumer serverConsumer = (ServerConsumer) consumer;
RemotingConnection connection = null;
for (RemotingConnection potentialConnection : remotingService.getConnections()) {
if (potentialConnection.getID().toString().equals(serverConsumer.getConnectionID())) {
connection = potentialConnection;
}
}
if (connection != null) {
remotingService.removeConnection(connection.getID());
connection.fail(ActiveMQMessageBundle.BUNDLE.consumerConnectionsClosedByManagement(address));
closed = true;
}
}
}
}
}
} catch (Exception e) {
ActiveMQServerLogger.LOGGER.failedToCloseConsumerConnectionsForAddress(address, e);
} finally {
blockOnIO();
}
return closed;
}
Aggregations