mirror of https://github.com/apache/activemq.git
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@675314 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
730aef4d1e
commit
f4012c5098
|
@ -18,7 +18,6 @@ package org.apache.activemq.broker;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
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;
|
||||||
|
@ -32,7 +31,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import org.apache.activemq.broker.ft.MasterBroker;
|
import org.apache.activemq.broker.ft.MasterBroker;
|
||||||
import org.apache.activemq.broker.region.ConnectionStatistics;
|
import org.apache.activemq.broker.region.ConnectionStatistics;
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
import org.apache.activemq.broker.region.RegionBroker;
|
||||||
|
@ -1152,7 +1150,7 @@ public class TransportConnection implements Connection, Task, CommandVisitor {
|
||||||
// now turn duplex off this side
|
// now turn duplex off this side
|
||||||
info.setDuplexConnection(false);
|
info.setDuplexConnection(false);
|
||||||
duplexBridge.setCreatedByDuplex(true);
|
duplexBridge.setCreatedByDuplex(true);
|
||||||
duplexBridge.duplexStart(brokerInfo, info);
|
duplexBridge.duplexStart(this,brokerInfo, info);
|
||||||
|
|
||||||
LOG.info("Created Duplex Bridge back to " + info.getBrokerName());
|
LOG.info("Created Duplex Bridge back to " + info.getBrokerName());
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -28,7 +28,9 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import org.apache.activemq.Service;
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
import org.apache.activemq.advisory.AdvisorySupport;
|
||||||
|
import org.apache.activemq.broker.TransportConnection;
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
import org.apache.activemq.command.ActiveMQDestination;
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
import org.apache.activemq.command.ActiveMQMessage;
|
||||||
import org.apache.activemq.command.ActiveMQTempDestination;
|
import org.apache.activemq.command.ActiveMQTempDestination;
|
||||||
|
@ -120,6 +122,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
|
||||||
|
|
||||||
|
|
||||||
private AtomicBoolean started = new AtomicBoolean();
|
private AtomicBoolean started = new AtomicBoolean();
|
||||||
|
private TransportConnection duplexInitiatingConnection;
|
||||||
|
|
||||||
public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) {
|
public DemandForwardingBridgeSupport(NetworkBridgeConfiguration configuration, Transport localBroker, Transport remoteBroker) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
|
@ -127,9 +130,10 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
|
||||||
this.remoteBroker = remoteBroker;
|
this.remoteBroker = remoteBroker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void duplexStart(BrokerInfo localBrokerInfo, BrokerInfo remoteBrokerInfo) throws Exception {
|
public void duplexStart(TransportConnection connection, BrokerInfo localBrokerInfo, BrokerInfo remoteBrokerInfo) throws Exception {
|
||||||
this.localBrokerInfo = localBrokerInfo;
|
this.localBrokerInfo = localBrokerInfo;
|
||||||
this.remoteBrokerInfo = remoteBrokerInfo;
|
this.remoteBrokerInfo = remoteBrokerInfo;
|
||||||
|
this.duplexInitiatingConnection = connection;
|
||||||
start();
|
start();
|
||||||
serviceRemoteCommand(remoteBrokerInfo);
|
serviceRemoteCommand(remoteBrokerInfo);
|
||||||
}
|
}
|
||||||
|
@ -381,7 +385,7 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
|
||||||
LOG.debug("The remote Exception was: " + error, error);
|
LOG.debug("The remote Exception was: " + error, error);
|
||||||
ASYNC_TASKS.execute(new Runnable() {
|
ASYNC_TASKS.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
ServiceSupport.dispose(DemandForwardingBridgeSupport.this);
|
ServiceSupport.dispose(getControllingService());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fireBridgeFailed();
|
fireBridgeFailed();
|
||||||
|
@ -533,13 +537,17 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge {
|
||||||
LOG.debug("The local Exception was:" + error, error);
|
LOG.debug("The local Exception was:" + error, error);
|
||||||
ASYNC_TASKS.execute(new Runnable() {
|
ASYNC_TASKS.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
ServiceSupport.dispose(DemandForwardingBridgeSupport.this);
|
ServiceSupport.dispose(getControllingService());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fireBridgeFailed();
|
fireBridgeFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Service getControllingService() {
|
||||||
|
return duplexInitiatingConnection != null ? duplexInitiatingConnection : DemandForwardingBridgeSupport.this;
|
||||||
|
}
|
||||||
|
|
||||||
protected void addSubscription(DemandSubscription sub) throws IOException {
|
protected void addSubscription(DemandSubscription sub) throws IOException {
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
localBroker.oneway(sub.getLocalInfo());
|
localBroker.oneway(sub.getLocalInfo());
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.activemq.command.MessageAck;
|
||||||
import org.apache.activemq.command.MessageId;
|
import org.apache.activemq.command.MessageId;
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
import org.apache.activemq.command.ProducerInfo;
|
||||||
import org.apache.activemq.command.SessionInfo;
|
import org.apache.activemq.command.SessionInfo;
|
||||||
|
import org.apache.activemq.command.XATransactionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to simulate the recovery that occurs when a broker shuts down.
|
* Used to simulate the recovery that occurs when a broker shuts down.
|
||||||
|
@ -235,7 +236,7 @@ public class RecoveryBrokerTest extends BrokerRestartTestSupport {
|
||||||
Message m = receiveMessage(connection);
|
Message m = receiveMessage(connection);
|
||||||
assertNull(m);
|
assertNull(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTopicDurableConsumerHoldsPersistentMessageAfterRestart() throws Exception {
|
public void testTopicDurableConsumerHoldsPersistentMessageAfterRestart() throws Exception {
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
||||||
|
@ -403,6 +404,7 @@ public class RecoveryBrokerTest extends BrokerRestartTestSupport {
|
||||||
|
|
||||||
assertNoMessagesLeft(connection);
|
assertNoMessagesLeft(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testQueuePersistentCommitedAcksNotLostOnRestart() throws Exception {
|
public void testQueuePersistentCommitedAcksNotLostOnRestart() throws Exception {
|
||||||
|
|
||||||
|
@ -456,6 +458,8 @@ public class RecoveryBrokerTest extends BrokerRestartTestSupport {
|
||||||
Message m = receiveMessage(connection);
|
Message m = receiveMessage(connection);
|
||||||
assertNull(m);
|
assertNull(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void testQueuePersistentUncommitedAcksLostOnRestart() throws Exception {
|
public void testQueuePersistentUncommitedAcksLostOnRestart() throws Exception {
|
||||||
|
|
||||||
|
@ -512,6 +516,62 @@ public class RecoveryBrokerTest extends BrokerRestartTestSupport {
|
||||||
|
|
||||||
assertNoMessagesLeft(connection);
|
assertNoMessagesLeft(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testQueuePersistentXAUncommitedAcksLostOnRestart() throws Exception {
|
||||||
|
int NUMBER = 100;
|
||||||
|
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
||||||
|
|
||||||
|
// Setup the producer and send the message.
|
||||||
|
StubConnection connection = createConnection();
|
||||||
|
ConnectionInfo connectionInfo = createConnectionInfo();
|
||||||
|
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
||||||
|
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
||||||
|
connection.send(connectionInfo);
|
||||||
|
connection.send(sessionInfo);
|
||||||
|
connection.send(producerInfo);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER; i++) {
|
||||||
|
Message message = createMessage(producerInfo, destination);
|
||||||
|
message.setPersistent(true);
|
||||||
|
connection.send(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the consumer and receive the message.
|
||||||
|
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
||||||
|
connection.send(consumerInfo);
|
||||||
|
|
||||||
|
// Begin the transaction.
|
||||||
|
XATransactionId txid = createXATransaction(sessionInfo);
|
||||||
|
connection.send(createBeginTransaction(connectionInfo, txid));
|
||||||
|
for (int i = 0; i < NUMBER; i++) {
|
||||||
|
Message m = receiveMessage(connection);
|
||||||
|
assertNotNull(m);
|
||||||
|
MessageAck ack = createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE);
|
||||||
|
ack.setTransactionId(txid);
|
||||||
|
connection.send(ack);
|
||||||
|
}
|
||||||
|
// Don't commit
|
||||||
|
|
||||||
|
// restart the broker.
|
||||||
|
restartBroker();
|
||||||
|
|
||||||
|
// Setup the consumer and receive the message.
|
||||||
|
connection = createConnection();
|
||||||
|
connectionInfo = createConnectionInfo();
|
||||||
|
sessionInfo = createSessionInfo(connectionInfo);
|
||||||
|
connection.send(connectionInfo);
|
||||||
|
connection.send(sessionInfo);
|
||||||
|
consumerInfo = createConsumerInfo(sessionInfo, destination);
|
||||||
|
connection.send(consumerInfo);
|
||||||
|
|
||||||
|
// All messages should be re-delivered.
|
||||||
|
for (int i = 0; i < NUMBER; i++) {
|
||||||
|
Message m = receiveMessage(connection);
|
||||||
|
assertNotNull(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNoMessagesLeft(connection);
|
||||||
|
}
|
||||||
|
|
||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
return suite(RecoveryBrokerTest.class);
|
return suite(RecoveryBrokerTest.class);
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/**
|
||||||
|
* 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.network;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.management.MBeanServerConnection;
|
||||||
|
import javax.management.ObjectInstance;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
import javax.management.remote.JMXConnectorFactory;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.activemq.broker.BrokerService;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
public class DuplexNetworkMBeanTest extends TestCase {
|
||||||
|
|
||||||
|
protected static final Log LOG = LogFactory.getLog(DuplexNetworkMBeanTest.class);
|
||||||
|
protected final int numRestarts = 2;
|
||||||
|
|
||||||
|
protected BrokerService createBroker() throws Exception {
|
||||||
|
BrokerService broker = new BrokerService();
|
||||||
|
broker.setBrokerName("broker");
|
||||||
|
broker.addConnector("tcp://localhost:61617");
|
||||||
|
|
||||||
|
return broker;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BrokerService createNetworkedBroker() throws Exception {
|
||||||
|
BrokerService broker = new BrokerService();
|
||||||
|
broker.setBrokerName("networkedBroker");
|
||||||
|
broker.addConnector("tcp://localhost:62617");
|
||||||
|
NetworkConnector networkConnector = broker.addNetworkConnector("static://tcp://localhost:61617");
|
||||||
|
networkConnector.setDuplex(true);
|
||||||
|
return broker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMbeanPresenceOnNetworkBrokerRestart() throws Exception {
|
||||||
|
BrokerService broker = createBroker();
|
||||||
|
broker.start();
|
||||||
|
assertEquals(1, countMbeans(broker, "Connector"));
|
||||||
|
assertEquals(0, countMbeans(broker, "Connection"));
|
||||||
|
BrokerService networkedBroker = null;
|
||||||
|
for (int i=0; i<numRestarts; i++) {
|
||||||
|
networkedBroker = createNetworkedBroker();
|
||||||
|
networkedBroker.start();
|
||||||
|
assertEquals(1, countMbeans(networkedBroker, "NetworkBridge", 2000));
|
||||||
|
assertEquals(1, countMbeans(broker, "Connection"));
|
||||||
|
networkedBroker.stop();
|
||||||
|
networkedBroker.waitUntilStopped();
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "stopped"));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "NetworkBridge"));
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "Connector"));
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "Connection"));
|
||||||
|
assertEquals(1, countMbeans(broker, "Connector"));
|
||||||
|
broker.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMbeanPresenceOnBrokerRestart() throws Exception {
|
||||||
|
|
||||||
|
BrokerService networkedBroker = createNetworkedBroker();
|
||||||
|
networkedBroker.start();
|
||||||
|
assertEquals(1, countMbeans(networkedBroker, "Connector"));
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "Connection"));
|
||||||
|
|
||||||
|
BrokerService broker = null;
|
||||||
|
for (int i=0; i<numRestarts; i++) {
|
||||||
|
broker = createBroker();
|
||||||
|
broker.start();
|
||||||
|
assertEquals(1, countMbeans(networkedBroker, "NetworkBridge", 5000));
|
||||||
|
assertEquals(1, countMbeans(broker, "Connection"));
|
||||||
|
|
||||||
|
broker.stop();
|
||||||
|
broker.waitUntilStopped();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "NetworkBridge"));
|
||||||
|
assertEquals(1, countMbeans(networkedBroker, "Connector"));
|
||||||
|
assertEquals(0, countMbeans(networkedBroker, "Connection"));
|
||||||
|
assertEquals(0, countMbeans(broker, "Connection"));
|
||||||
|
|
||||||
|
networkedBroker.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countMbeans(BrokerService broker, String type) throws Exception {
|
||||||
|
return countMbeans(broker, type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countMbeans(BrokerService broker, String type, int timeout) throws Exception {
|
||||||
|
final long expiryTime = System.currentTimeMillis() + timeout;
|
||||||
|
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
|
||||||
|
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
|
||||||
|
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
|
||||||
|
|
||||||
|
Set all = mbsc.queryMBeans(null, null);
|
||||||
|
LOG.info("MBean total=" + all.size());
|
||||||
|
for (Object o : all) {
|
||||||
|
ObjectInstance bean = (ObjectInstance)o;
|
||||||
|
LOG.info(bean.getObjectName());
|
||||||
|
}
|
||||||
|
ObjectName beanName = new ObjectName("org.apache.activemq:BrokerName="
|
||||||
|
+ broker.getBrokerName() + ",Type=" + type +",*");
|
||||||
|
Set mbeans = null;
|
||||||
|
do {
|
||||||
|
if (timeout > 0) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
mbeans = mbsc.queryMBeans(beanName, null);
|
||||||
|
} while (mbeans.isEmpty() && expiryTime > System.currentTimeMillis());
|
||||||
|
return mbeans.size();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue