use of org.apache.activemq.artemis.core.remoting.FailureListener in project activemq-artemis by apache.
the class ClientSessionFactoryImpl method reconnectSessions.
/*
* Re-attach sessions all pre-existing sessions to the new remoting connection
*/
private void reconnectSessions(final RemotingConnection oldConnection, final int reconnectAttempts, final ActiveMQException cause) {
HashSet<ClientSessionInternal> sessionsToFailover;
synchronized (sessions) {
sessionsToFailover = new HashSet<>(sessions);
}
for (ClientSessionInternal session : sessionsToFailover) {
session.preHandleFailover(connection);
}
getConnectionWithRetry(reconnectAttempts);
if (connection == null) {
if (!clientProtocolManager.isAlive())
ActiveMQClientLogger.LOGGER.failedToConnectToServer();
return;
}
List<FailureListener> oldListeners = oldConnection.getFailureListeners();
List<FailureListener> newListeners = new ArrayList<>(connection.getFailureListeners());
for (FailureListener listener : oldListeners) {
// Add all apart from the old DelegatingFailureListener
if (listener instanceof DelegatingFailureListener == false) {
newListeners.add(listener);
}
}
connection.setFailureListeners(newListeners);
// This used to be done inside failover
// it needs to be done on the protocol
((CoreRemotingConnection) connection).syncIDGeneratorSequence(((CoreRemotingConnection) oldConnection).getIDGeneratorSequence());
for (ClientSessionInternal session : sessionsToFailover) {
session.handleFailover(connection, cause);
}
}
use of org.apache.activemq.artemis.core.remoting.FailureListener in project activemq-artemis by apache.
the class ServerSessionPacketHandler method internaltransferConnection.
private int internaltransferConnection(final CoreRemotingConnection newConnection, final int lastReceivedCommandID) {
// We need to disable delivery on all the consumers while the transfer is occurring- otherwise packets might get
// delivered
// after the channel has transferred but *before* packets have been replayed - this will give the client the wrong
// sequence of packets.
// It is not sufficient to just stop the session, since right after stopping the session, another session start
// might be executed
// before we have transferred the connection, leaving it in a started state
session.setTransferring(true);
List<CloseListener> closeListeners = remotingConnection.removeCloseListeners();
List<FailureListener> failureListeners = remotingConnection.removeFailureListeners();
// Note. We do not destroy the replicating connection here. In the case the live server has really crashed
// then the connection will get cleaned up anyway when the server ping timeout kicks in.
// In the case the live server is really still up, i.e. a split brain situation (or in tests), then closing
// the replicating connection will cause the outstanding responses to be be replayed on the live server,
// if these reach the client who then subsequently fails over, on reconnection to backup, it will have
// received responses that the backup did not know about.
channel.transferConnection(newConnection);
newConnection.syncIDGeneratorSequence(remotingConnection.getIDGeneratorSequence());
Connection oldTransportConnection = remotingConnection.getTransportConnection();
remotingConnection = newConnection;
remotingConnection.setCloseListeners(closeListeners);
remotingConnection.setFailureListeners(failureListeners);
int serverLastReceivedCommandID = channel.getLastConfirmedCommandID();
channel.replayCommands(lastReceivedCommandID);
channel.setTransferring(false);
session.setTransferring(false);
// We do this because the old connection could be out of credits on netty
// this will force anything to resume after the reattach through the ReadyListener callbacks
oldTransportConnection.fireReady(true);
return serverLastReceivedCommandID;
}
use of org.apache.activemq.artemis.core.remoting.FailureListener in project activemq-artemis by apache.
the class AmqpOutboundConnectionTest method runOutboundConnectionTest.
private void runOutboundConnectionTest(boolean withSecurity, boolean closeFromClient) throws Exception {
final ActiveMQServer remote;
try {
securityEnabled = withSecurity;
remote = createServer(AMQP_PORT + 1);
} finally {
securityEnabled = false;
}
Wait.assertTrue(remote::isActive);
final Map<String, Object> config = new LinkedHashMap<>();
config.put(TransportConstants.HOST_PROP_NAME, "localhost");
config.put(TransportConstants.PORT_PROP_NAME, String.valueOf(AMQP_PORT + 1));
final ClientSASLFactory clientSASLFactory;
if (withSecurity) {
clientSASLFactory = availableMechanims -> {
if (availableMechanims != null && Arrays.asList(availableMechanims).contains("PLAIN")) {
return new PlainSASLMechanism(fullUser, fullPass);
} else {
return null;
}
};
} else {
clientSASLFactory = null;
}
final AtomicBoolean connectionOpened = new AtomicBoolean();
EventHandler eventHandler = new EventHandler() {
@Override
public void onRemoteOpen(Connection connection) throws Exception {
connectionOpened.set(true);
}
};
ProtonClientConnectionManager lifeCycleListener = new ProtonClientConnectionManager(new AMQPClientConnectionFactory(server, "myid", Collections.singletonMap(Symbol.getSymbol("myprop"), "propvalue"), 5000), Optional.of(eventHandler), clientSASLFactory);
ProtonClientProtocolManager protocolManager = new ProtonClientProtocolManager(new ProtonProtocolManagerFactory(), server);
NettyConnector connector = new NettyConnector(config, lifeCycleListener, lifeCycleListener, server.getExecutorFactory().getExecutor(), server.getExecutorFactory().getExecutor(), server.getScheduledPool(), protocolManager);
connector.start();
Object connectionId = connector.createConnection().getID();
assertNotNull(connectionId);
RemotingConnection remotingConnection = lifeCycleListener.getConnection(connectionId);
AtomicReference<ActiveMQException> ex = new AtomicReference<>();
AtomicBoolean closed = new AtomicBoolean(false);
remotingConnection.addCloseListener(() -> closed.set(true));
remotingConnection.addFailureListener(new FailureListener() {
@Override
public void connectionFailed(ActiveMQException exception, boolean failedOver) {
ex.set(exception);
}
@Override
public void connectionFailed(ActiveMQException exception, boolean failedOver, String scaleDownTargetNodeID) {
ex.set(exception);
}
});
try {
Wait.assertEquals(1, remote::getConnectionCount);
Wait.assertTrue(connectionOpened::get);
if (closeFromClient) {
lifeCycleListener.stop();
} else {
remote.stop();
}
Wait.assertEquals(0, remote::getConnectionCount);
assertTrue(remotingConnection.isDestroyed());
if (!closeFromClient) {
assertTrue(ex.get() instanceof ActiveMQRemoteDisconnectException);
} else {
assertNull(ex.get());
}
} finally {
if (closeFromClient) {
remote.stop();
} else {
lifeCycleListener.stop();
}
}
}
use of org.apache.activemq.artemis.core.remoting.FailureListener in project activemq-artemis by apache.
the class LiveVoteOnBackupFailureClusterTest method testLiveVoteSucceedsAfterBackupFailure.
@Test
public void testLiveVoteSucceedsAfterBackupFailure() throws Exception {
startCluster();
// Wait for servers to start
for (int i = 0; i < servers.length; i++) {
waitForServerToStart(servers[i]);
}
// Wait for backup to sync replication
for (int i = 3; i < servers.length; i++) {
Wait.waitFor(() -> servers[3].isReplicaSync());
}
// Register failure listener to detect when live recognises the backup has died.
final CountDownLatch latch = new CountDownLatch(1);
servers[0].getReplicationManager().getBackupTransportConnection().addFailureListener(new FailureListener() {
@Override
public void connectionFailed(ActiveMQException exception, boolean failedOver) {
latch.countDown();
}
@Override
public void connectionFailed(ActiveMQException exception, boolean failedOver, String scaleDownTargetNodeID) {
latch.countDown();
}
});
servers[3].stop();
// Wait for live to notice backup is down.
latch.await(30, TimeUnit.SECONDS);
// The quorum vote time out is hardcoded 5s. Wait for double the time then check server is live
Thread.sleep(10000);
assertTrue(servers[0].isStarted());
}
use of org.apache.activemq.artemis.core.remoting.FailureListener in project activemq-artemis by apache.
the class BindingsClusterTest method crash.
private void crash() throws Exception {
/*
* Rather than just calling stop() on the server here we want to simulate an actual node crash or bridge failure
* so the bridge's failure listener needs to get something other than a DISCONNECTED message. In this case we
* simulate a NOT_CONNECTED exception.
*/
final CountDownLatch latch = new CountDownLatch(1);
ClusterConnectionImpl next = (ClusterConnectionImpl) server1.getClusterManager().getClusterConnections().iterator().next();
BridgeImpl bridge = (BridgeImpl) next.getRecords().values().iterator().next().getBridge();
RemotingConnection forwardingConnection = getForwardingConnection(bridge);
forwardingConnection.addFailureListener(new FailureListener() {
@Override
public void connectionFailed(ActiveMQException exception, boolean failedOver) {
latch.countDown();
}
@Override
public void connectionFailed(final ActiveMQException me, boolean failedOver, String scaleDownTargetNodeID) {
connectionFailed(me, failedOver);
}
});
forwardingConnection.fail(new ActiveMQNotConnectedException());
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
if (crash) {
jmsServer2.stop();
}
}
Aggregations