From c7622d58c0b1da7f51718f7a8db74ca355431e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Andr=C3=A9=20Pearce?= Date: Wed, 14 Mar 2018 22:13:48 +0000 Subject: [PATCH] ARTEMIS-1747 - Fix Configuration change loss when network Issue Add Test Case to stop and restart server after config reload and check state, this re-creates network health check issue where config changes are lost when network health check de-activates the server and then re-activates. Add fix to update the held configuration thats used when initialisation steps during start are done. --- .../core/server/impl/ActiveMQServerImpl.java | 7 + .../tests/integration/jms/RedeployTest.java | 114 ++++++++++++ .../src/test/resources/reload-changed.xml | 155 ++++++++++++++++ .../src/test/resources/reload-original.xml | 168 ++++++++++++++++++ 4 files changed, 444 insertions(+) create mode 100644 tests/integration-tests/src/test/resources/reload-changed.xml create mode 100644 tests/integration-tests/src/test/resources/reload-original.xml diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index d2ae179783..bcbbca1bee 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -3107,17 +3107,24 @@ public class ActiveMQServerImpl implements ActiveMQServer { Configuration config = new FileConfigurationParser().parseMainConfig(uri.openStream()); ActiveMQServerLogger.LOGGER.reloadingConfiguration("security"); securityRepository.swap(config.getSecurityRoles().entrySet()); + configuration.setSecurityRoles(config.getSecurityRoles()); + ActiveMQServerLogger.LOGGER.reloadingConfiguration("address settings"); addressSettingsRepository.swap(config.getAddressesSettings().entrySet()); + configuration.setAddressesSettings(config.getAddressesSettings()); + ActiveMQServerLogger.LOGGER.reloadingConfiguration("diverts"); for (DivertConfiguration divertConfig : config.getDivertConfigurations()) { if (postOffice.getBinding(new SimpleString(divertConfig.getName())) == null) { deployDivert(divertConfig); } } + ActiveMQServerLogger.LOGGER.reloadingConfiguration("addresses"); deployAddressesFromConfiguration(config); undeployAddressesAndQueueNotInConfiguration(config); + configuration.setAddressConfigurations(config.getAddressConfigurations()); + configuration.setQueueConfigurations(config.getQueueConfigurations()); } } } diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java index f474e71c6c..f216c2a620 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTest.java @@ -28,12 +28,15 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.core.postoffice.QueueBinding; +import org.apache.activemq.artemis.core.security.Role; import org.apache.activemq.artemis.core.server.impl.AddressInfo; +import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; @@ -179,6 +182,117 @@ public class RedeployTest extends ActiveMQTestBase { } } + + + /** + * Simulates Stop and Start that occurs when network health checker stops the server when network is detected unhealthy + * and re-starts the broker once detected that it is healthy again. + * + * @throws Exception for anything un-expected, test will fail. + */ + @Test + public void testRedeployStopAndRestart() throws Exception { + Path brokerXML = getTestDirfile().toPath().resolve("broker.xml"); + URL url1 = RedeployTest.class.getClassLoader().getResource("reload-original.xml"); + URL url2 = RedeployTest.class.getClassLoader().getResource("reload-changed.xml"); + Files.copy(url1.openStream(), brokerXML); + + EmbeddedJMS embeddedJMS = new EmbeddedJMS(); + embeddedJMS.setConfigResourcePath(brokerXML.toUri().toString()); + embeddedJMS.start(); + + final ReusableLatch latch = new ReusableLatch(1); + + Runnable tick = latch::countDown; + + embeddedJMS.getActiveMQServer().getReloadManager().setTick(tick); + + try { + latch.await(10, TimeUnit.SECONDS); + + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").size(), 1); + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").iterator().next().getName(), "b"); + + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getDeadLetterAddress(), SimpleString.toSimpleString("OriginalDLQ")); + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getExpiryAddress(), SimpleString.toSimpleString("OriginalExpiryQueue")); + + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_address_removal_no_queue")); + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_address_removal")); + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_removal")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_1")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_2")); + + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_change")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_change").contains("config_test_queue_change_queue")); + Assert.assertEquals(10, getQueue(embeddedJMS, "config_test_queue_change_queue").getMaxConsumers()); + Assert.assertEquals(false, getQueue(embeddedJMS, "config_test_queue_change_queue").isPurgeOnNoConsumers()); + + Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING); + brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000); + latch.setCount(1); + embeddedJMS.getActiveMQServer().getReloadManager().setTick(tick); + latch.await(10, TimeUnit.SECONDS); + + //Assert that the security settings change applied + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").size(), 1); + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").iterator().next().getName(), "c"); + + //Assert that the address settings change applied + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getDeadLetterAddress(), SimpleString.toSimpleString("NewDLQ")); + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getExpiryAddress(), SimpleString.toSimpleString("NewExpiryQueue")); + + //Assert the address and queue changes applied + Assert.assertNull(getAddressInfo(embeddedJMS, "config_test_address_removal_no_queue")); + Assert.assertNull(getAddressInfo(embeddedJMS, "config_test_address_removal")); + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_removal")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_1")); + Assert.assertFalse(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_2")); + + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_change")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_change").contains("config_test_queue_change_queue")); + Assert.assertEquals(1, getQueue(embeddedJMS, "config_test_queue_change_queue").getMaxConsumers()); + Assert.assertEquals(true, getQueue(embeddedJMS, "config_test_queue_change_queue").isPurgeOnNoConsumers()); + } finally { + embeddedJMS.stop(); + } + + + try { + embeddedJMS.start(); + + //Assert that the security settings changes persist a stop and start server (e.g. like what occurs if network health check stops the node), but JVM remains up. + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").size(), 1); + Assert.assertEquals(getSecurityRoles(embeddedJMS, "security_address").iterator().next().getName(), "c"); + + //Assert that the address settings changes persist a stop and start server (e.g. like what occurs if network health check stops the node), but JVM remains up. + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getDeadLetterAddress(), SimpleString.toSimpleString("NewDLQ")); + Assert.assertEquals(getAddressSettings(embeddedJMS, "address_settings_address").getExpiryAddress(), SimpleString.toSimpleString("NewExpiryQueue")); + + //Assert that the address and queue changes persist a stop and start server (e.g. like what occurs if network health check stops the node), but JVM remains up. + Assert.assertNull(getAddressInfo(embeddedJMS, "config_test_address_removal_no_queue")); + Assert.assertNull(getAddressInfo(embeddedJMS, "config_test_address_removal")); + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_removal")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_1")); + Assert.assertFalse(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_removal").contains("config_test_queue_removal_queue_2")); + + Assert.assertNotNull(getAddressInfo(embeddedJMS, "config_test_queue_change")); + Assert.assertTrue(listQueuesNamesForAddress(embeddedJMS, "config_test_queue_change").contains("config_test_queue_change_queue")); + Assert.assertEquals(1, getQueue(embeddedJMS, "config_test_queue_change_queue").getMaxConsumers()); + Assert.assertEquals(true, getQueue(embeddedJMS, "config_test_queue_change_queue").isPurgeOnNoConsumers()); + + } finally { + embeddedJMS.stop(); + } + } + + private AddressSettings getAddressSettings(EmbeddedJMS embeddedJMS, String address) { + return embeddedJMS.getActiveMQServer().getAddressSettingsRepository().getMatch(address); + } + + private Set getSecurityRoles(EmbeddedJMS embeddedJMS, String address) { + return embeddedJMS.getActiveMQServer().getSecurityRepository().getMatch(address); + } + private AddressInfo getAddressInfo(EmbeddedJMS embeddedJMS, String address) { return embeddedJMS.getActiveMQServer().getPostOffice().getAddressInfo(SimpleString.toSimpleString(address)); } diff --git a/tests/integration-tests/src/test/resources/reload-changed.xml b/tests/integration-tests/src/test/resources/reload-changed.xml new file mode 100644 index 0000000000..2ed7878dda --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-changed.xml @@ -0,0 +1,155 @@ + + + + + + + + 0.0.0.0 + + 100 + + false + + false + + + NIO + + ./data/paging + + ./data/bindings + + ./data/journal + + ./data/large-messages + + 2 + + -1 + + + 40000 + + + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + tcp://0.0.0.0:5672?protocols=AMQP + + + tcp://0.0.0.0:61613?protocols=STOMP + + + tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP + + + tcp://0.0.0.0:1883?protocols=MQTT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10Mb + 10 + BLOCK + + + + false + DLQ + ExpiryQueue + 0 + 10Mb + 10 + BLOCK + FORCE + FORCE + + + + false + NewDLQ + NewExpiryQueue + 0 + 10Mb + 10 + BLOCK + FORCE + FORCE + + + + + _ + + + +
+ + + +
+
+ + + +
+
+
+
diff --git a/tests/integration-tests/src/test/resources/reload-original.xml b/tests/integration-tests/src/test/resources/reload-original.xml new file mode 100644 index 0000000000..45476ac13d --- /dev/null +++ b/tests/integration-tests/src/test/resources/reload-original.xml @@ -0,0 +1,168 @@ + + + + + + + + 0.0.0.0 + + 100 + + false + + false + + + NIO + + ./data/paging + + ./data/bindings + + ./data/journal + + ./data/large-messages + + 2 + + -1 + + + 40000 + + + + + + tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576 + + + tcp://0.0.0.0:5672?protocols=AMQP + + + tcp://0.0.0.0:61613?protocols=STOMP + + + tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP + + + tcp://0.0.0.0:1883?protocols=MQTT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + DLQ + ExpiryQueue + 0 + 10Mb + 10 + BLOCK + + + + false + DLQ + ExpiryQueue + 0 + 10Mb + 10 + BLOCK + FORCE + FORCE + + + + false + OriginalDLQ + OriginalExpiryQueue + 0 + 10Mb + 10 + BLOCK + FORCE + FORCE + + + + + _ + + + +
+ + + + +
+
+ + + +
+
+ + +
+
+ + + +
+
+
+