mirror of https://github.com/apache/activemq.git
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:
parent
9bd267ed8d
commit
df8d3d4a63
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue