mirror of
https://github.com/apache/activemq.git
synced 2025-02-13 05:26:47 +00:00
apply fix and updated test for: https://issues.apache.org/jira/browse/AMQ-4148
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1438123 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
61cbe46fc6
commit
c5184983cf
@ -25,7 +25,6 @@ import java.util.List;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -140,7 +139,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
private TransportConnection duplexInitiatingConnection;
|
private TransportConnection duplexInitiatingConnection;
|
||||||
private BrokerService brokerService = null;
|
private BrokerService brokerService = null;
|
||||||
private ObjectName mbeanObjectName;
|
private ObjectName mbeanObjectName;
|
||||||
private ExecutorService serialExecutor = Executors.newSingleThreadExecutor();
|
private final ExecutorService serialExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) {
|
public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
@ -156,6 +155,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
serviceRemoteCommand(remoteBrokerInfo);
|
serviceRemoteCommand(remoteBrokerInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void start() throws Exception {
|
public void start() throws Exception {
|
||||||
if (started.compareAndSet(false, true)) {
|
if (started.compareAndSet(false, true)) {
|
||||||
|
|
||||||
@ -178,11 +178,13 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
});
|
});
|
||||||
remoteBroker.setTransportListener(new DefaultTransportListener() {
|
remoteBroker.setTransportListener(new DefaultTransportListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onCommand(Object o) {
|
public void onCommand(Object o) {
|
||||||
Command command = (Command) o;
|
Command command = (Command) o;
|
||||||
serviceRemoteCommand(command);
|
serviceRemoteCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onException(IOException error) {
|
public void onException(IOException error) {
|
||||||
serviceRemoteException(error);
|
serviceRemoteException(error);
|
||||||
}
|
}
|
||||||
@ -206,6 +208,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
|
|
||||||
protected void triggerLocalStartBridge() throws IOException {
|
protected void triggerLocalStartBridge() throws IOException {
|
||||||
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final String originalName = Thread.currentThread().getName();
|
final String originalName = Thread.currentThread().getName();
|
||||||
Thread.currentThread().setName("StartLocalBridge: localBroker=" + localBroker);
|
Thread.currentThread().setName("StartLocalBridge: localBroker=" + localBroker);
|
||||||
@ -222,6 +225,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
|
|
||||||
protected void triggerRemoteStartBridge() throws IOException {
|
protected void triggerRemoteStartBridge() throws IOException {
|
||||||
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final String originalName = Thread.currentThread().getName();
|
final String originalName = Thread.currentThread().getName();
|
||||||
Thread.currentThread().setName("StartRemoteBridge: remoteBroker=" + remoteBroker);
|
Thread.currentThread().setName("StartRemoteBridge: remoteBroker=" + remoteBroker);
|
||||||
@ -344,6 +348,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() throws Exception {
|
public void stop() throws Exception {
|
||||||
if (started.compareAndSet(true, false)) {
|
if (started.compareAndSet(true, false)) {
|
||||||
if (disposed.compareAndSet(false, true)) {
|
if (disposed.compareAndSet(false, true)) {
|
||||||
@ -357,6 +362,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
final CountDownLatch sendShutdown = new CountDownLatch(1);
|
final CountDownLatch sendShutdown = new CountDownLatch(1);
|
||||||
|
|
||||||
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
serialExecutor.shutdown();
|
serialExecutor.shutdown();
|
||||||
@ -400,6 +406,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void serviceRemoteException(Throwable error) {
|
public void serviceRemoteException(Throwable error) {
|
||||||
if (!disposed.get()) {
|
if (!disposed.get()) {
|
||||||
if (error instanceof SecurityException || error instanceof GeneralSecurityException) {
|
if (error instanceof SecurityException || error instanceof GeneralSecurityException) {
|
||||||
@ -409,6 +416,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
}
|
}
|
||||||
LOG.debug("The remote Exception was: " + error, error);
|
LOG.debug("The remote Exception was: " + error, error);
|
||||||
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ServiceSupport.dispose(getControllingService());
|
ServiceSupport.dispose(getControllingService());
|
||||||
}
|
}
|
||||||
@ -631,6 +639,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
if (destInfo.isRemoveOperation()) {
|
if (destInfo.isRemoveOperation()) {
|
||||||
// serialise with removeSub operations such that all removeSub advisories are generated
|
// serialise with removeSub operations such that all removeSub advisories are generated
|
||||||
serialExecutor.execute(new Runnable() {
|
serialExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
localBroker.oneway(destInfo);
|
localBroker.oneway(destInfo);
|
||||||
@ -648,11 +657,13 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void serviceLocalException(Throwable error) {
|
public void serviceLocalException(Throwable error) {
|
||||||
if (!disposed.get()) {
|
if (!disposed.get()) {
|
||||||
LOG.info("Network connection between " + localBroker + " and " + remoteBroker + " shutdown due to a local error: " + error);
|
LOG.info("Network connection between " + localBroker + " and " + remoteBroker + " shutdown due to a local error: " + error);
|
||||||
LOG.debug("The local Exception was:" + error, error);
|
LOG.debug("The local Exception was:" + error, error);
|
||||||
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
brokerService.getTaskRunnerFactory().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ServiceSupport.dispose(getControllingService());
|
ServiceSupport.dispose(getControllingService());
|
||||||
}
|
}
|
||||||
@ -683,6 +694,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
// serialise with removeDestination operations so that removeSubs are serialised with removeDestinations
|
// serialise with removeDestination operations so that removeSubs are serialised with removeDestinations
|
||||||
// such that all removeSub advisories are generated
|
// such that all removeSub advisories are generated
|
||||||
serialExecutor.execute(new Runnable() {
|
serialExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sub.waitForCompletion();
|
sub.waitForCompletion();
|
||||||
try {
|
try {
|
||||||
@ -760,6 +772,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
// broker when we get confirmation that the remote
|
// broker when we get confirmation that the remote
|
||||||
// broker has received the message.
|
// broker has received the message.
|
||||||
ResponseCallback callback = new ResponseCallback() {
|
ResponseCallback callback = new ResponseCallback() {
|
||||||
|
@Override
|
||||||
public void onCompletion(FutureResponse future) {
|
public void onCompletion(FutureResponse future) {
|
||||||
try {
|
try {
|
||||||
Response response = future.getResult();
|
Response response = future.getResult();
|
||||||
@ -1184,6 +1197,9 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
ConsumerInfo info = new ConsumerInfo();
|
ConsumerInfo info = new ConsumerInfo();
|
||||||
info.setDestination(destination);
|
info.setDestination(destination);
|
||||||
|
|
||||||
|
// Indicate that this subscription is being made on behalf of the remote broker.
|
||||||
|
info.setBrokerPath(new BrokerId[] { remoteBrokerId });
|
||||||
|
|
||||||
// the remote info held by the DemandSubscription holds the original consumerId,
|
// the remote info held by the DemandSubscription holds the original consumerId,
|
||||||
// the local info get's overwritten
|
// the local info get's overwritten
|
||||||
info.setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId()));
|
info.setConsumerId(new ConsumerId(localSessionInfo.getSessionId(), consumerIdGenerator.getNextSequenceId()));
|
||||||
@ -1307,6 +1323,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
return remoteBrokerPath;
|
return remoteBrokerPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setNetworkBridgeListener(NetworkBridgeListener listener) {
|
public void setNetworkBridgeListener(NetworkBridgeListener listener) {
|
||||||
this.networkBridgeListener = listener;
|
this.networkBridgeListener = listener;
|
||||||
}
|
}
|
||||||
@ -1318,26 +1335,32 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getRemoteAddress() {
|
public String getRemoteAddress() {
|
||||||
return remoteBroker.getRemoteAddress();
|
return remoteBroker.getRemoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getLocalAddress() {
|
public String getLocalAddress() {
|
||||||
return localBroker.getRemoteAddress();
|
return localBroker.getRemoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getRemoteBrokerName() {
|
public String getRemoteBrokerName() {
|
||||||
return remoteBrokerInfo == null ? null : remoteBrokerInfo.getBrokerName();
|
return remoteBrokerInfo == null ? null : remoteBrokerInfo.getBrokerName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getLocalBrokerName() {
|
public String getLocalBrokerName() {
|
||||||
return localBrokerInfo == null ? null : localBrokerInfo.getBrokerName();
|
return localBrokerInfo == null ? null : localBrokerInfo.getBrokerName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long getDequeueCounter() {
|
public long getDequeueCounter() {
|
||||||
return dequeueCounter.get();
|
return dequeueCounter.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long getEnqueueCounter() {
|
public long getEnqueueCounter() {
|
||||||
return enqueueCounter.get();
|
return enqueueCounter.get();
|
||||||
}
|
}
|
||||||
@ -1350,16 +1373,19 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
|||||||
return subscriptionMapByRemoteId;
|
return subscriptionMapByRemoteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setBrokerService(BrokerService brokerService) {
|
public void setBrokerService(BrokerService brokerService) {
|
||||||
this.brokerService = brokerService;
|
this.brokerService = brokerService;
|
||||||
this.localBrokerId = brokerService.getRegionBroker().getBrokerId();
|
this.localBrokerId = brokerService.getRegionBroker().getBrokerId();
|
||||||
localBrokerPath[0] = localBrokerId;
|
localBrokerPath[0] = localBrokerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setMbeanObjectName(ObjectName objectName) {
|
public void setMbeanObjectName(ObjectName objectName) {
|
||||||
this.mbeanObjectName = objectName;
|
this.mbeanObjectName = objectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ObjectName getMbeanObjectName() {
|
public ObjectName getMbeanObjectName() {
|
||||||
return mbeanObjectName;
|
return mbeanObjectName;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.activemq.bugs;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.activemq.JmsMultipleBrokersTestSupport;
|
||||||
|
import org.apache.activemq.broker.BrokerService;
|
||||||
|
import org.apache.activemq.broker.region.Destination;
|
||||||
|
import org.apache.activemq.command.ActiveMQDestination;
|
||||||
|
import org.apache.activemq.network.DemandForwardingBridgeSupport;
|
||||||
|
import org.apache.activemq.network.NetworkConnector;
|
||||||
|
import org.apache.activemq.util.Wait;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test demonstrates a bug in {@link DemandForwardingBridgeSupport} whereby
|
||||||
|
* a static subscription from broker1 to broker2 is forwarded to broker3 even
|
||||||
|
* though the network TTL is 1. This results in duplicate subscriptions on
|
||||||
|
* broker3.
|
||||||
|
*/
|
||||||
|
public class AMQ4148Test extends JmsMultipleBrokersTestSupport {
|
||||||
|
|
||||||
|
public void test() throws Exception {
|
||||||
|
// Create a hub-and-spoke network where each hub-spoke pair share
|
||||||
|
// messages on a test queue.
|
||||||
|
BrokerService hub = createBroker(new URI("broker:(vm://hub)/hub?persistent=false"));
|
||||||
|
|
||||||
|
final BrokerService[] spokes = new BrokerService[4];
|
||||||
|
for (int i = 0; i < spokes.length; i++) {
|
||||||
|
spokes[i] = createBroker(new URI("broker:(vm://spoke" + i + ")/spoke" + i + "?persistent=false"));
|
||||||
|
|
||||||
|
}
|
||||||
|
startAllBrokers();
|
||||||
|
|
||||||
|
ActiveMQDestination testQueue = createDestination(AMQ4148Test.class.getSimpleName() + ".queue", false);
|
||||||
|
|
||||||
|
NetworkConnector[] ncs = new NetworkConnector[spokes.length];
|
||||||
|
for (int i = 0; i < spokes.length; i++) {
|
||||||
|
NetworkConnector nc = bridgeBrokers("hub", "spoke" + i);
|
||||||
|
nc.setNetworkTTL(1);
|
||||||
|
nc.setDuplex(true);
|
||||||
|
nc.setConduitSubscriptions(false);
|
||||||
|
nc.setStaticallyIncludedDestinations(Arrays.asList(testQueue));
|
||||||
|
nc.start();
|
||||||
|
|
||||||
|
ncs[i] = nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForBridgeFormation();
|
||||||
|
|
||||||
|
// Pause to allow subscriptions to be created.
|
||||||
|
TimeUnit.SECONDS.sleep(5);
|
||||||
|
|
||||||
|
// Verify that the hub has a subscription from each spoke, but that each
|
||||||
|
// spoke has a single subscription from the hub (since the network TTL is 1).
|
||||||
|
final Destination hubTestQueue = hub.getDestination(testQueue);
|
||||||
|
assertTrue("Expecting {" + spokes.length + "} consumer but was {" + hubTestQueue.getConsumers().size() + "}",
|
||||||
|
Wait.waitFor(new Wait.Condition() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSatisified() throws Exception {
|
||||||
|
return spokes.length == hubTestQueue.getConsumers().size();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now check each spoke has exactly one consumer on the Queue.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
Destination spokeTestQueue = spokes[i].getDestination(testQueue);
|
||||||
|
Assert.assertEquals(1, spokeTestQueue.getConsumers().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NetworkConnector nc : ncs) {
|
||||||
|
nc.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user