merge -c 835715 Fix for http://issues.apache.org/activemq/browse/AMQ-2439: IllegalState issue.

Tightening synchronization in DemandForwardingBridge to avoid subscription clean up and ack processing race condition.

git-svn-id: https://svn.apache.org/repos/asf/activemq/branches/activemq-5.3@835920 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gary Tully 2009-11-13 17:00:14 +00:00
parent 9bd267ed8d
commit df8d3d4a63
3 changed files with 118 additions and 107 deletions

View File

@ -131,7 +131,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
private BrokerInfo localBrokerInfo; private BrokerInfo localBrokerInfo;
private BrokerInfo remoteBrokerInfo; private BrokerInfo remoteBrokerInfo;
private AtomicBoolean started = new AtomicBoolean(); private AtomicBoolean started = new AtomicBoolean();
private TransportConnection duplexInitiatingConnection; private TransportConnection duplexInitiatingConnection;
private BrokerService brokerService = null; private BrokerService brokerService = null;
@ -675,7 +674,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
enqueueCounter.incrementAndGet(); enqueueCounter.incrementAndGet();
final MessageDispatch md = (MessageDispatch) command; final MessageDispatch md = (MessageDispatch) command;
final DemandSubscription sub = subscriptionMapByLocalId.get(md.getConsumerId()); final DemandSubscription sub = subscriptionMapByLocalId.get(md.getConsumerId());
if (sub != null && md.getMessage()!=null) { if (sub != null && md.getMessage() != null && sub.incrementOutstandingResponses()) {
// See if this consumer's brokerPath tells us it came from the broker at the other end // See if this consumer's brokerPath tells us it came from the broker at the other end
// of the bridge. I think we should be making this decision based on the message's // of the bridge. I think we should be making this decision based on the message's
// broker bread crumbs and not the consumer's? However, the message's broker bread // broker bread crumbs and not the consumer's? However, the message's broker bread
@ -697,6 +696,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
// by bridging it using an async send (small chance // by bridging it using an async send (small chance
// of message loss). // of message loss).
try {
// Don't send it off to the remote if it originally came from the remote. // Don't send it off to the remote if it originally came from the remote.
if (!cameFromRemote) { if (!cameFromRemote) {
remoteBroker.oneway(message); remoteBroker.oneway(message);
@ -705,8 +705,12 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
LOG.debug("Message not forwarded on to remote, because message came from remote"); LOG.debug("Message not forwarded on to remote, because message came from remote");
} }
} }
localBroker.oneway(new MessageAck(md, MessageAck.INDIVIDUAL_ACK_TYPE, 1)); localBroker.oneway(new MessageAck(md, MessageAck.INDIVIDUAL_ACK_TYPE, 1));
dequeueCounter.incrementAndGet(); dequeueCounter.incrementAndGet();
} finally {
sub.decrementOutstandingResponses();
}
} else { } else {
@ -735,7 +739,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
}; };
remoteBroker.asyncRequest(message, callback); remoteBroker.asyncRequest(message, callback);
sub.incrementOutstandingResponses();
} }
} else { } else {
@ -1014,7 +1017,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
return suppress; return suppress;
} }
private boolean hasLowerPriority(Subscription existingSub, ConsumerInfo candidateInfo) { private boolean hasLowerPriority(Subscription existingSub, ConsumerInfo candidateInfo) {
boolean suppress = false; boolean suppress = false;
@ -1075,7 +1077,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
return doCreateDemandSubscription(info); return doCreateDemandSubscription(info);
} }
protected DemandSubscription doCreateDemandSubscription(ConsumerInfo info) throws IOException { protected DemandSubscription doCreateDemandSubscription(ConsumerInfo info) throws IOException {
DemandSubscription result = new DemandSubscription(info); DemandSubscription result = new DemandSubscription(info);
result.getLocalInfo().setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId())); result.getLocalInfo().setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId()));
@ -1132,7 +1133,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
sub.getLocalInfo().setAdditionalPredicate(createNetworkBridgeFilter(info)); sub.getLocalInfo().setAdditionalPredicate(createNetworkBridgeFilter(info));
} }
protected void removeDemandSubscription(ConsumerId id) throws IOException { protected void removeDemandSubscription(ConsumerId id) throws IOException {
DemandSubscription sub = subscriptionMapByRemoteId.remove(id); DemandSubscription sub = subscriptionMapByRemoteId.remove(id);
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
@ -1178,7 +1178,6 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
protected abstract void serviceRemoteBrokerInfo(Command command) throws IOException; protected abstract void serviceRemoteBrokerInfo(Command command) throws IOException;
protected abstract BrokerId[] getRemoteBrokerPath(); protected abstract BrokerId[] getRemoteBrokerPath();
public void setNetworkBridgeListener(NetworkBridgeListener listener) { public void setNetworkBridgeListener(NetworkBridgeListener listener) {

View File

@ -37,6 +37,7 @@ public class DemandSubscription {
private final ConsumerInfo remoteInfo; private final ConsumerInfo remoteInfo;
private final ConsumerInfo localInfo; private final ConsumerInfo localInfo;
private Set<ConsumerId> remoteSubsIds = new CopyOnWriteArraySet<ConsumerId>(); private Set<ConsumerId> remoteSubsIds = new CopyOnWriteArraySet<ConsumerId>();
private AtomicInteger dispatched = new AtomicInteger(0); private AtomicInteger dispatched = new AtomicInteger(0);
private AtomicBoolean activeWaiter = new AtomicBoolean(); private AtomicBoolean activeWaiter = new AtomicBoolean();
@ -81,7 +82,6 @@ public class DemandSubscription {
return localInfo; return localInfo;
} }
/** /**
* @return Returns the remoteInfo. * @return Returns the remoteInfo.
*/ */
@ -117,7 +117,12 @@ public class DemandSubscription {
} }
} }
public void incrementOutstandingResponses() { public boolean incrementOutstandingResponses() {
dispatched.incrementAndGet(); dispatched.incrementAndGet();
if (activeWaiter.get()) {
decrementOutstandingResponses();
return false;
}
return true;
} }
} }

View File

@ -65,12 +65,19 @@ public class ResponseCorrelator extends TransportFilter {
command.setCommandId(sequenceGenerator.getNextSequenceId()); command.setCommandId(sequenceGenerator.getNextSequenceId());
command.setResponseRequired(true); command.setResponseRequired(true);
FutureResponse future = new FutureResponse(responseCallback); FutureResponse future = new FutureResponse(responseCallback);
IOException priorError = null;
synchronized (requestMap) { synchronized (requestMap) {
if( this.error !=null ) { priorError = this.error;
throw error; if (priorError == null) {
}
requestMap.put(new Integer(command.getCommandId()), future); requestMap.put(new Integer(command.getCommandId()), future);
} }
}
if (priorError != null) {
future.set(new ExceptionResponse(priorError));
throw priorError;
}
next.oneway(command); next.oneway(command);
return future; return future;
} }