diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java index 0451437ef6..8aabd1b1b9 100644 --- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java @@ -26,7 +26,11 @@ import org.apache.activemq.artemis.api.core.SimpleString; public class RandomUtil { // Constants ----------------------------------------------------- - protected static final Random random = new Random(System.currentTimeMillis()); + protected static final Random random = new Random(); + + public static Random getRandom() { + return random; + } // Attributes ---------------------------------------------------- @@ -75,7 +79,7 @@ public class RandomUtil { } public static int randomInterval(final int min, final int max) { - return min + randomMax(max - min); + return min + random.nextInt(max - min); } public static int randomMax(final int max) { diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomConnectionLoadBalancingPolicy.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomConnectionLoadBalancingPolicy.java index 4ab66a3290..e411c9c2fd 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomConnectionLoadBalancingPolicy.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomConnectionLoadBalancingPolicy.java @@ -16,7 +16,7 @@ */ package org.apache.activemq.artemis.api.core.client.loadbalance; -import org.apache.activemq.artemis.utils.Random; +import org.apache.activemq.artemis.utils.RandomUtil; /** * {@link RandomConnectionLoadBalancingPolicy#select(int)} returns a (pseudo) random integer between @@ -24,8 +24,6 @@ import org.apache.activemq.artemis.utils.Random; */ public final class RandomConnectionLoadBalancingPolicy implements ConnectionLoadBalancingPolicy { - private final Random random = new Random(); - /** * Returns a pseudo random number between {@code 0} (inclusive) and {@code max} exclusive. * @@ -34,6 +32,6 @@ public final class RandomConnectionLoadBalancingPolicy implements ConnectionLoad */ @Override public int select(final int max) { - return random.getRandom().nextInt(max); + return RandomUtil.randomInterval(0, max); } } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomStickyConnectionLoadBalancingPolicy.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomStickyConnectionLoadBalancingPolicy.java index 5e269a9483..12c59fd151 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomStickyConnectionLoadBalancingPolicy.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RandomStickyConnectionLoadBalancingPolicy.java @@ -16,15 +16,13 @@ */ package org.apache.activemq.artemis.api.core.client.loadbalance; -import org.apache.activemq.artemis.utils.Random; +import org.apache.activemq.artemis.utils.RandomUtil; /** * {@link RandomConnectionLoadBalancingPolicy#select(int)} chooses a the initial node randomly then subsequent requests return the same node */ public final class RandomStickyConnectionLoadBalancingPolicy implements ConnectionLoadBalancingPolicy { - private final Random random = new Random(); - private int pos = -1; /** @@ -33,7 +31,7 @@ public final class RandomStickyConnectionLoadBalancingPolicy implements Connecti @Override public int select(final int max) { if (pos == -1) { - pos = random.getRandom().nextInt(max); + pos = RandomUtil.randomInterval(0, max); } return pos; diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RoundRobinConnectionLoadBalancingPolicy.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RoundRobinConnectionLoadBalancingPolicy.java index cdf0828e2a..58694b601e 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RoundRobinConnectionLoadBalancingPolicy.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/loadbalance/RoundRobinConnectionLoadBalancingPolicy.java @@ -18,7 +18,7 @@ package org.apache.activemq.artemis.api.core.client.loadbalance; import java.io.Serializable; -import org.apache.activemq.artemis.utils.Random; +import org.apache.activemq.artemis.utils.RandomUtil; /** * RoundRobinConnectionLoadBalancingPolicy corresponds to a round-robin load-balancing policy. @@ -31,8 +31,6 @@ public final class RoundRobinConnectionLoadBalancingPolicy implements Connection private static final long serialVersionUID = 7511196010141439559L; - private final Random random = new Random(); - private boolean first = true; private int pos; @@ -41,7 +39,7 @@ public final class RoundRobinConnectionLoadBalancingPolicy implements Connection public int select(final int max) { if (first) { // We start on a random one - pos = random.getRandom().nextInt(max); + pos = RandomUtil.randomInterval(0, max); first = false; } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientLogger.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientLogger.java index 244f76f642..6ed0e12a50 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientLogger.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientLogger.java @@ -206,7 +206,7 @@ public interface ActiveMQClientLogger extends BasicLogger { @LogMessage(level = Logger.Level.WARN) @Message(id = 212035, value = "error receiving packet in discovery", format = Message.Format.MESSAGE_FORMAT) - void errorReceivingPAcketInDiscovery(@Cause Throwable e); + void errorReceivingPacketInDiscovery(@Cause Throwable e); @LogMessage(level = Logger.Level.WARN) @Message(id = 212036, diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java index 4c3fdb9dc8..4e9fce58da 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/cluster/DiscoveryGroup.java @@ -272,7 +272,7 @@ public final class DiscoveryGroup implements ActiveMQComponent { return; } else { - ActiveMQClientLogger.LOGGER.errorReceivingPAcketInDiscovery(e); + ActiveMQClientLogger.LOGGER.errorReceivingPacketInDiscovery(e); } } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/Random.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/Random.java deleted file mode 100644 index b93fd7e9da..0000000000 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/Random.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.utils; - -import java.io.Serializable; - -public class Random implements Serializable { - - private static int extraSeed; - - private static final long serialVersionUID = 40335522290950498L; - - private static synchronized long getSeed() { - long seed = System.currentTimeMillis() + Random.extraSeed++; - - return seed; - } - - private final java.util.Random random = new java.util.Random(Random.getSeed()); - - public java.util.Random getRandom() { - return random; - } - -} diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilDistributionTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilDistributionTest.java new file mode 100644 index 0000000000..68b348a3a1 --- /dev/null +++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/util/RandomUtilDistributionTest.java @@ -0,0 +1,102 @@ +/** + * 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.unit.core.util; + + +import java.util.HashSet; + +import org.apache.activemq.artemis.tests.util.SpawnedVMSupport; +import org.apache.activemq.artemis.utils.RandomUtil; +import org.junit.Assert; +import org.junit.Test; + +/** This test will start many parallel VMs, to make sure each VM would generate a good distribution of random numbers */ +public class RandomUtilDistributionTest { + public static void main(String[] arg) { + + long start = Long.parseLong(arg[0]); + + try { + Thread.sleep((start - System.currentTimeMillis()) / 2); + } + catch (Exception e) { + } + while (System.currentTimeMillis() < start) { + Thread.yield(); + } + int value; + value = RandomUtil.randomInterval(0, 255); + System.exit(value); + } + + @Test + public void testDistribution() throws Exception { + int numberOfStarts = 50; + int iterations = 10; + + int value = 0; + for (int i = 0; i < iterations; i++) { + + int v = internalDistributionTest(numberOfStarts); + + value += v; + } + + // I'm using an extra parenthesis here to avoid rounding problems. + // Be careful removing it (make sure you know what you're doing in case you do so) + int minimumExpected = (int)((iterations * numberOfStarts) * 0.80); + + System.out.println("value=" + value + ", minimum expected = " + minimumExpected); + Assert.assertTrue("The Random distribution is pretty bad. All tries have returned duplicated randoms. value=" + value + ", minimum expected = " + minimumExpected, value > minimumExpected); + + } + + private int internalDistributionTest(int numberOfTries) throws Exception { + long timeStart = System.currentTimeMillis() + 5000; + Process[] process = new Process[numberOfTries]; + int[] value = new int[numberOfTries]; + try { + for (int i = 0; i < numberOfTries; i++) { + process[i] = SpawnedVMSupport.spawnVM(RandomUtilDistributionTest.class.getName(), true, "" + timeStart); + } + + + HashSet valueSet = new HashSet<>(); + + for (int i = 0; i < numberOfTries; i++) { + value[i] = process[i].waitFor(); + Assert.assertTrue(value[i] >= 0); + valueSet.add(process[i].exitValue()); + } + + System.out.println("Generated " + valueSet.size() + " randoms out of " + numberOfTries + " tries"); + + return valueSet.size(); + + + } + finally { + for (Process p : process) { + if (p != null) { + p.destroy(); + } + } + } + } + +} diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/UTF8Test.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/UTF8Test.java index 26c5e9d3a4..ffaf6aa755 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/UTF8Test.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/UTF8Test.java @@ -32,7 +32,6 @@ import java.nio.ByteBuffer; import org.junit.Assert; import org.apache.activemq.artemis.utils.DataConstants; -import org.apache.activemq.artemis.utils.Random; import org.apache.activemq.artemis.utils.RandomUtil; import org.apache.activemq.artemis.utils.UTF8Util; @@ -44,8 +43,7 @@ public class UTF8Test extends ActiveMQTestBase { byte[] bytes = new byte[20000]; - Random random = new Random(); - random.getRandom().nextBytes(bytes); + RandomUtil.getRandom().nextBytes(bytes); String str = new String(bytes); @@ -59,12 +57,11 @@ public class UTF8Test extends ActiveMQTestBase { @Test public void testValidateUTFOnDataInput() throws Exception { for (int i = 0; i < 100; i++) { - Random random = new Random(); // Random size between 15k and 20K byte[] bytes = new byte[15000 + RandomUtil.randomPositiveInt() % 5000]; - random.getRandom().nextBytes(bytes); + RandomUtil.getRandom().nextBytes(bytes); String str = new String(bytes);