/* * 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.artemis.tests.integration.cluster.failover; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.client.ClientConsumer; import org.apache.activemq.artemis.api.core.client.ClientProducer; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ServerLocator; import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal; import org.apache.activemq.artemis.core.config.ScaleDownConfiguration; import org.apache.activemq.artemis.core.config.ha.ColocatedPolicyConfiguration; import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration; import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.impl.InVMNodeManager; import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils; import org.junit.Assert; import org.junit.Test; public class LiveToLiveFailoverTest extends FailoverTest { private InVMNodeManager nodeManager0; private InVMNodeManager nodeManager1; private ClientSessionFactoryInternal sf2; @Override public void setUp() throws Exception { super.setUp(); } @Override protected void createConfigs() throws Exception { nodeManager0 = new InVMNodeManager(false); nodeManager1 = new InVMNodeManager(false); TransportConfiguration liveConnector0 = getConnectorTransportConfiguration(true, 0); TransportConfiguration liveConnector1 = getConnectorTransportConfiguration(true, 1); backupConfig = super.createDefaultInVMConfig(1).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(true, 1)).setHAPolicyConfiguration(new ColocatedPolicyConfiguration().setRequestBackup(true).setLiveConfig(new SharedStoreMasterPolicyConfiguration()).setBackupConfig(new SharedStoreSlavePolicyConfiguration().setScaleDownConfiguration(new ScaleDownConfiguration().addConnector(liveConnector1.getName())))).addConnectorConfiguration(liveConnector0.getName(), liveConnector0).addConnectorConfiguration(liveConnector1.getName(), liveConnector1).addClusterConfiguration(basicClusterConnectionConfig(liveConnector1.getName(), liveConnector0.getName())); backupServer = createColocatedTestableServer(backupConfig, nodeManager1, nodeManager0, 1); liveConfig = super.createDefaultInVMConfig(0).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(true, 0)).setHAPolicyConfiguration(new ColocatedPolicyConfiguration().setRequestBackup(true).setBackupRequestRetryInterval(1000).setLiveConfig(new SharedStoreMasterPolicyConfiguration()).setBackupConfig(new SharedStoreSlavePolicyConfiguration().setScaleDownConfiguration(new ScaleDownConfiguration()))).addConnectorConfiguration(liveConnector0.getName(), liveConnector0).addConnectorConfiguration(liveConnector1.getName(), liveConnector1).addClusterConfiguration(basicClusterConnectionConfig(liveConnector0.getName(), liveConnector1.getName())); liveServer = createColocatedTestableServer(liveConfig, nodeManager0, nodeManager1, 0); } @Override protected void setLiveIdentity() { liveServer.setIdentity(this.getClass().getSimpleName() + "/liveServer0"); } @Override protected void setBackupIdentity() { backupServer.setIdentity(this.getClass().getSimpleName() + "/liveServer1"); } @Override protected void waitForBackup() { Map<String, ActiveMQServer> backupServers0 = liveServer.getServer().getClusterManager().getHAManager().getBackupServers(); Map<String, ActiveMQServer> backupServers1 = backupServer.getServer().getClusterManager().getHAManager().getBackupServers(); final long toWait = 10000; final long time = System.currentTimeMillis(); while (true) { if (backupServers0.size() == 1 && backupServers1.size() == 1) { break; } if (System.currentTimeMillis() > (time + toWait)) { fail("backup started? ( live server0 backups = " + backupServers0.size() + " live server1 backups = " + backupServers1.size() + ")"); } try { Thread.sleep(100); } catch (InterruptedException e) { fail(e.getMessage()); } } waitForRemoteBackupSynchronization(backupServers0.values().iterator().next()); waitForRemoteBackupSynchronization(backupServers1.values().iterator().next()); } @Override protected final ClientSessionFactoryInternal createSessionFactoryAndWaitForTopology(ServerLocator locator, int topologyMembers) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(topologyMembers * 2); locator.addClusterTopologyListener(new LatchClusterTopologyListener(countDownLatch)); ClientSessionFactoryInternal sf = (ClientSessionFactoryInternal) locator.createSessionFactory(); addSessionFactory(sf); assertTrue("topology members expected " + topologyMembers, countDownLatch.await(5, TimeUnit.SECONDS)); closeSessionFactory(sf); sf = (ClientSessionFactoryInternal) locator.createSessionFactory(liveServer.getServer().getNodeID().toString()); addSessionFactory(sf); if (sf2 == null) { sf2 = (ClientSessionFactoryInternal) locator.createSessionFactory(backupServer.getServer().getNodeID().toString()); ClientSession session2 = createSession(sf2, false, false); session2.createQueue(ADDRESS, ADDRESS, null, true); addSessionFactory(sf2); } return sf; } protected final ClientSessionFactoryInternal createSessionFactoryAndWaitForTopology(ServerLocator locator, TransportConfiguration transportConfiguration, int topologyMembers) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(topologyMembers * 2); locator.addClusterTopologyListener(new LatchClusterTopologyListener(countDownLatch)); ClientSessionFactoryInternal sf = (ClientSessionFactoryInternal) locator.createSessionFactory(transportConfiguration); addSessionFactory(sf); assertTrue("topology members expected " + topologyMembers, countDownLatch.await(5, TimeUnit.SECONDS)); closeSessionFactory(sf); sf = (ClientSessionFactoryInternal) locator.createSessionFactory(liveServer.getServer().getNodeID().toString()); addSessionFactory(sf); if (sf2 == null) { sf2 = (ClientSessionFactoryInternal) locator.createSessionFactory(backupServer.getServer().getNodeID().toString()); ClientSession session2 = createSession(sf2, false, false); session2.createQueue(ADDRESS, ADDRESS, null, true); addSessionFactory(sf2); } return sf; } @Override protected void createClientSessionFactory() throws Exception { if (liveServer.getServer().isStarted()) { sf = (ClientSessionFactoryInternal) createSessionFactory(locator); sf = (ClientSessionFactoryInternal) locator.createSessionFactory(liveServer.getServer().getNodeID().toString()); } else { sf = (ClientSessionFactoryInternal) createSessionFactory(locator); } } @Override protected void createSessionFactory() throws Exception { locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setReconnectAttempts(-1); sf = createSessionFactoryAndWaitForTopology(locator, getConnectorTransportConfiguration(true, 0), 2); if (sf2 == null) { sf2 = (ClientSessionFactoryInternal) locator.createSessionFactory(backupServer.getServer().getNodeID().toString()); addSessionFactory(sf2); ClientSession session2 = createSession(sf2, false, false); session2.createQueue(ADDRESS, ADDRESS, null, true); } } private TransportConfiguration getConnectorTransportConfiguration(boolean live, int server) { return TransportConfigurationUtils.getInVMConnector(live, server); } private TransportConfiguration getAcceptorTransportConfiguration(boolean live, int server) { return TransportConfigurationUtils.getInVMAcceptor(live, server); } @Test public void scaleDownDelay() throws Exception { createSessionFactory(); ClientSession session = createSession(sf, true, true); session.createQueue(ADDRESS, ADDRESS, null, true); ClientProducer producer = session.createProducer(ADDRESS); //send enough messages to ensure that when the client fails over scaledown hasn't complete sendMessages(session, producer, 1000); crash(session); ClientConsumer consumer = session.createConsumer(ADDRESS); session.start(); receiveDurableMessages(consumer); session.close(); sf.close(); Assert.assertEquals(0, sf.numSessions()); Assert.assertEquals(0, sf.numConnections()); } // https://jira.jboss.org/jira/browse/HORNETQ-285 @Override @Test public void testFailoverOnInitialConnection() throws Exception { locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setFailoverOnInitialConnection(true).setReconnectAttempts(-1); sf = createSessionFactoryAndWaitForTopology(locator, 2); // Crash live server crash(); ClientSession session = createSession(sf); //session.createQueue(FailoverTestBase.ADDRESS, FailoverTestBase.ADDRESS, null, true); ClientProducer producer = session.createProducer(ADDRESS); sendMessages(session, producer, NUM_MESSAGES); ClientConsumer consumer = session.createConsumer(ADDRESS); session.start(); receiveMessages(consumer); session.close(); } @Override @Test public void testCreateNewFactoryAfterFailover() throws Exception { locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setFailoverOnInitialConnection(true); sf = createSessionFactoryAndWaitForTopology(locator, 2); ClientSession session = sendAndConsume(sf, true); crash(true, session); session.close(); long timeout; timeout = System.currentTimeMillis() + 5000; while (timeout > System.currentTimeMillis()) { try { createClientSessionFactory(); break; } catch (Exception e) { // retrying Thread.sleep(100); } } session = sendAndConsume(sf, false); } //invalid tests for Live to Live failover //all the timeout ones aren't as we don't migrate timeouts, any failback or server restart //or replicating tests aren't either @Override public void testLiveAndBackupBackupComesBackNewFactory() throws Exception { } @Override public void testLiveAndBackupLiveComesBackNewFactory() { } @Override public void testTimeoutOnFailoverConsumeBlocked() throws Exception { } @Override public void testFailoverMultipleSessionsWithConsumers() throws Exception { // } @Override public void testTimeoutOnFailover() throws Exception { } @Override public void testTimeoutOnFailoverTransactionRollback() throws Exception { } @Override public void testTimeoutOnFailoverConsume() throws Exception { } @Override public void testTimeoutOnFailoverTransactionCommit() throws Exception { } @Override public void testFailBack() throws Exception { } @Override public void testFailBackLiveRestartsBackupIsGone() throws Exception { } @Override public void testLiveAndBackupLiveComesBack() throws Exception { } @Override public void testSimpleFailover() throws Exception { } @Override public void testFailThenReceiveMoreMessagesAfterFailover2() throws Exception { } @Override public void testWithoutUsingTheBackup() throws Exception { } //todo check to see which failing tests are valid, @Override public void testSimpleSendAfterFailoverDurableNonTemporary() throws Exception { } @Override public void testCommitOccurredUnblockedAndResendNoDuplicates() throws Exception { } /*@Override public void testCommitDidNotOccurUnblockedAndResend() throws Exception { } @Override public void testLiveAndBackupLiveComesBackNewFactory() throws Exception { } @Override public void testXAMessagesSentSoRollbackOnEnd() throws Exception { } @Override public void testLiveAndBackupBackupComesBackNewFactory() throws Exception { } @Override public void testXAMessagesSentSoRollbackOnEnd2() throws Exception { } @Override public void testXAMessagesSentSoRollbackOnCommit() throws Exception { } @Override public void testTransactedMessagesSentSoRollback() throws Exception { } @Override public void testXAMessagesSentSoRollbackOnPrepare() throws Exception { } @Override public void testNonTransactedWithZeroConsumerWindowSize() throws Exception { }*/ }