mirror of https://github.com/apache/activemq.git
In the queue case, when a consumer was closed it was not properly re-delivering messages to other available consumers. This was causing message to look like they got dropped.
- When we shut a queue sub down we now get it's pending+dispatched list and re-dispatch that to the other available subscriptions. git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@640890 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f9585fd6ab
commit
ae7de6c236
|
@ -17,6 +17,9 @@
|
||||||
package org.apache.activemq.broker.region;
|
package org.apache.activemq.broker.region;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import javax.jms.InvalidSelectorException;
|
import javax.jms.InvalidSelectorException;
|
||||||
|
@ -104,8 +107,9 @@ public abstract class AbstractSubscription implements Subscription {
|
||||||
destinations.add(destination);
|
destinations.add(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(ConnectionContext context, Destination destination) throws Exception {
|
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||||
destinations.remove(destination);
|
destinations.remove(destination);
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConsumerInfo getConsumerInfo() {
|
public ConsumerInfo getConsumerInfo() {
|
||||||
|
|
|
@ -436,11 +436,18 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(ConnectionContext context, Destination destination) throws Exception {
|
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||||
|
List<MessageReference> rc = new ArrayList<MessageReference>();
|
||||||
synchronized(pendingLock) {
|
synchronized(pendingLock) {
|
||||||
super.remove(context, destination);
|
super.remove(context, destination);
|
||||||
pending.remove(context, destination);
|
for (MessageReference r : dispatched) {
|
||||||
|
if( r.getRegionDestination() == destination ) {
|
||||||
|
rc.add((QueueMessageReference)r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc.addAll(pending.remove(context, destination));
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void dispatchPending() throws IOException {
|
protected void dispatchPending() throws IOException {
|
||||||
|
|
|
@ -292,25 +292,20 @@ public class Queue extends BaseDestination implements Task {
|
||||||
ConsumerId consumerId = sub.getConsumerInfo().getConsumerId();
|
ConsumerId consumerId = sub.getConsumerInfo().getConsumerId();
|
||||||
MessageGroupSet ownedGroups = getMessageGroupOwners()
|
MessageGroupSet ownedGroups = getMessageGroupOwners()
|
||||||
.removeConsumer(consumerId);
|
.removeConsumer(consumerId);
|
||||||
|
|
||||||
// redeliver inflight messages
|
// redeliver inflight messages
|
||||||
sub.remove(context, this);
|
|
||||||
|
|
||||||
List<QueueMessageReference> list = new ArrayList<QueueMessageReference>();
|
List<QueueMessageReference> list = new ArrayList<QueueMessageReference>();
|
||||||
List<QueueMessageReference> inFlight = null;
|
for (MessageReference ref : sub.remove(context, this)) {
|
||||||
synchronized(pagedInMessages) {
|
QueueMessageReference qmr = (QueueMessageReference)ref;
|
||||||
inFlight = new ArrayList<QueueMessageReference>(pagedInMessages.values());
|
qmr.incrementRedeliveryCounter();
|
||||||
|
if( qmr.getLockOwner()==sub ) {
|
||||||
|
qmr.unlock();
|
||||||
|
qmr.incrementRedeliveryCounter();
|
||||||
|
}
|
||||||
|
list.add(qmr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (QueueMessageReference node:inFlight){
|
if (!list.isEmpty() && !consumers.isEmpty()) {
|
||||||
if (!node.isDropped() && !node.isAcked()
|
|
||||||
&& node.getLockOwner() == sub) {
|
|
||||||
if (node.unlock()) {
|
|
||||||
node.incrementRedeliveryCounter();
|
|
||||||
list.add(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (list != null && !consumers.isEmpty()) {
|
|
||||||
doDispatch(list);
|
doDispatch(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -938,6 +933,7 @@ public class Queue extends BaseDestination implements Task {
|
||||||
if( rd.subscription instanceof QueueBrowserSubscription ) {
|
if( rd.subscription instanceof QueueBrowserSubscription ) {
|
||||||
((QueueBrowserSubscription)rd.subscription).decrementQueueRef();
|
((QueueBrowserSubscription)rd.subscription).decrementQueueRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,9 @@ public interface Subscription extends SubscriptionRecovery {
|
||||||
* The subscription will be no longer be receiving messages from the destination.
|
* The subscription will be no longer be receiving messages from the destination.
|
||||||
* @param context
|
* @param context
|
||||||
* @param destination
|
* @param destination
|
||||||
|
* @return a list of un-acked messages that were added to the subscription.
|
||||||
*/
|
*/
|
||||||
void remove(ConnectionContext context, Destination destination) throws Exception;
|
List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ConsumerInfo object that created the subscription.
|
* The ConsumerInfo object that created the subscription.
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.broker.region.cursors;
|
package org.apache.activemq.broker.region.cursors;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQMessageAudit;
|
import org.apache.activemq.ActiveMQMessageAudit;
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
import org.apache.activemq.broker.region.Destination;
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
|
import org.apache.activemq.broker.region.QueueMessageReference;
|
||||||
import org.apache.activemq.command.MessageId;
|
import org.apache.activemq.command.MessageId;
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
|
||||||
|
@ -59,7 +62,9 @@ public class AbstractPendingMessageCursor implements PendingMessageCursor {
|
||||||
public void add(ConnectionContext context, Destination destination) throws Exception {
|
public void add(ConnectionContext context, Destination destination) throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(ConnectionContext context, Destination destination) throws Exception {
|
@SuppressWarnings("unchecked")
|
||||||
|
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRecoveryRequired() {
|
public boolean isRecoveryRequired() {
|
||||||
|
|
|
@ -111,6 +111,8 @@ public class FilePendingMessageCursor extends AbstractPendingMessageCursor imple
|
||||||
return isDiskListEmpty();
|
return isDiskListEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset the cursor
|
* reset the cursor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,12 +18,14 @@ package org.apache.activemq.broker.region.cursors;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQMessageAudit;
|
import org.apache.activemq.ActiveMQMessageAudit;
|
||||||
import org.apache.activemq.Service;
|
import org.apache.activemq.Service;
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
import org.apache.activemq.broker.region.Destination;
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
|
import org.apache.activemq.broker.region.QueueMessageReference;
|
||||||
import org.apache.activemq.command.MessageId;
|
import org.apache.activemq.command.MessageId;
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ public interface PendingMessageCursor extends Service {
|
||||||
* @param destination
|
* @param destination
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
void remove(ConnectionContext context, Destination destination) throws Exception;
|
List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if there are no pending messages
|
* @return true if there are no pending messages
|
||||||
|
|
|
@ -17,9 +17,11 @@
|
||||||
package org.apache.activemq.broker.region.cursors;
|
package org.apache.activemq.broker.region.cursors;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
import org.apache.activemq.advisory.AdvisorySupport;
|
||||||
|
@ -27,6 +29,7 @@ import org.apache.activemq.broker.Broker;
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
import org.apache.activemq.broker.region.Destination;
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
|
import org.apache.activemq.broker.region.QueueMessageReference;
|
||||||
import org.apache.activemq.broker.region.Subscription;
|
import org.apache.activemq.broker.region.Subscription;
|
||||||
import org.apache.activemq.broker.region.Topic;
|
import org.apache.activemq.broker.region.Topic;
|
||||||
import org.apache.activemq.command.Message;
|
import org.apache.activemq.command.Message;
|
||||||
|
@ -128,11 +131,12 @@ public class StoreDurableSubscriberCursor extends AbstractPendingMessageCursor {
|
||||||
* @param destination
|
* @param destination
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public synchronized void remove(ConnectionContext context, Destination destination) throws Exception {
|
public synchronized List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||||
Object tsp = topics.remove(destination);
|
Object tsp = topics.remove(destination);
|
||||||
if (tsp != null) {
|
if (tsp != null) {
|
||||||
storePrefetches.remove(tsp);
|
storePrefetches.remove(tsp);
|
||||||
}
|
}
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,8 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.broker.region.cursors;
|
package org.apache.activemq.broker.region.cursors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
import org.apache.activemq.broker.region.QueueMessageReference;
|
import org.apache.activemq.broker.region.QueueMessageReference;
|
||||||
|
|
||||||
|
@ -32,6 +37,18 @@ public class VMPendingMessageCursor extends AbstractPendingMessageCursor {
|
||||||
private Iterator<MessageReference> iter;
|
private Iterator<MessageReference> iter;
|
||||||
private MessageReference last;
|
private MessageReference last;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||||
|
List<MessageReference> rc = new ArrayList<MessageReference>();
|
||||||
|
for (MessageReference r : list) {
|
||||||
|
if( r.getRegionDestination()==destination ) {
|
||||||
|
rc.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc ;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if there are no pending messages
|
* @return true if there are no pending messages
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue