/* * 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.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.client.ClientConsumer; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.client.ClientProducer; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal; import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType; import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase; import org.apache.activemq.artemis.tests.util.CountDownSessionFailureListener; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class ReplicatedDistributionTest extends ClusterTestBase { private static final SimpleString ADDRESS = new SimpleString("test.SomeAddress"); private ClientSession sessionOne; private ClientSession sessionThree; private ClientConsumer consThree; private ClientProducer producer; @Test public void testRedistribution() throws Exception { commonTestCode(); for (int i = 0; i < 50; i++) { ClientMessage msg = consThree.receive(15000); Assert.assertNotNull(msg); // System.out.println(i + " msg = " + msg); int received = msg.getIntProperty("key"); Assert.assertEquals(i, received); msg.acknowledge(); } sessionThree.commit(); // consThree.close(); // TODO: Remove this sleep: If a node fail, // Redistribution may loose messages between the nodes. Thread.sleep(500); fail(sessionThree); // sessionThree.close(); // // setupSessionFactory(2, -1, true); // // sessionThree = sfs[2].createSession(true, true); // // sessionThree.start(); // consThree = sessionThree.createConsumer(ADDRESS); for (int i = 50; i < 100; i++) { ClientMessage msg = consThree.receive(15000); Assert.assertNotNull(msg); // System.out.println(i + " msg = " + msg); int received = (Integer) msg.getObjectProperty(new SimpleString("key")); Assert.assertEquals(i, received); msg.acknowledge(); } Assert.assertNull(consThree.receiveImmediate()); sessionThree.commit(); sessionOne.start(); ClientConsumer consOne = sessionOne.createConsumer(ReplicatedDistributionTest.ADDRESS); Assert.assertNull(consOne.receiveImmediate()); } @Test public void testSimpleRedistribution() throws Exception { commonTestCode(); for (int i = 0; i < 100; i++) { ClientMessage msg = consThree.receive(15000); Assert.assertNotNull(msg); // System.out.println(i + " msg = " + msg); int received = msg.getIntProperty("key"); if (i != received) { // Shouldn't this be a failure? System.out.println(i + "!=" + received); } msg.acknowledge(); } sessionThree.commit(); sessionOne.start(); ClientConsumer consOne = sessionOne.createConsumer(ReplicatedDistributionTest.ADDRESS); Assert.assertNull(consOne.receiveImmediate()); } private void commonTestCode() throws Exception { waitForBindings(3, "test.SomeAddress", 1, 1, true); waitForBindings(1, "test.SomeAddress", 1, 1, false); producer = sessionOne.createProducer(ReplicatedDistributionTest.ADDRESS); for (int i = 0; i < 100; i++) { ClientMessage msg = sessionOne.createMessage(true); msg.putIntProperty(new SimpleString("key"), i); producer.send(msg); } sessionOne.commit(); } /** * @param session * @throws InterruptedException */ private void fail(final ClientSession session) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); session.addFailureListener(new CountDownSessionFailureListener(latch, session)); RemotingConnection conn = ((ClientSessionInternal) session).getConnection(); // Simulate failure on connection conn.fail(new ActiveMQNotConnectedException()); // Wait to be informed of failure boolean ok = latch.await(1000, TimeUnit.MILLISECONDS); Assert.assertTrue(ok); } @Override @Before public void setUp() throws Exception { super.setUp(); setupLiveServer(1, true, isSharedStore(), true, false); setupLiveServer(3, true, isSharedStore(), true, false); setupBackupServer(2, 3, true, isSharedStore(), true); final String address = ReplicatedDistributionTest.ADDRESS.toString(); // notice the abuse of the method call, '3' is not a backup for '1' setupClusterConnectionWithBackups("test", address, MessageLoadBalancingType.ON_DEMAND, 1, true, 1, new int[]{3}); setupClusterConnectionWithBackups("test", address, MessageLoadBalancingType.ON_DEMAND, 1, true, 3, new int[]{2, 1}); setupClusterConnectionWithBackups("test", address, MessageLoadBalancingType.ON_DEMAND, 1, true, 2, new int[]{3}); AddressSettings as = new AddressSettings().setRedistributionDelay(0); for (int i : new int[]{1, 2, 3}) { getServer(i).getAddressSettingsRepository().addMatch("test.*", as); getServer(i).start(); } setupSessionFactory(1, -1, true, true); setupSessionFactory(3, 2, true, true); sessionOne = sfs[1].createSession(true, true); sessionThree = sfs[3].createSession(false, false); sessionOne.createQueue(ReplicatedDistributionTest.ADDRESS, ReplicatedDistributionTest.ADDRESS, true); sessionThree.createQueue(ReplicatedDistributionTest.ADDRESS, ReplicatedDistributionTest.ADDRESS, true); consThree = sessionThree.createConsumer(ReplicatedDistributionTest.ADDRESS); sessionThree.start(); } @Override protected boolean isSharedStore() { return false; } }