From 42be518deb538ad67c8b12afb70ea12144b6f4a0 Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Thu, 5 Oct 2023 11:43:35 -0400 Subject: [PATCH] ARTEMIS-4450 Caching hasLocal boolean on bindings to avoid transversing the maps on every call --- .../artemis/core/postoffice/Bindings.java | 4 +-- .../core/postoffice/impl/BindingsImpl.java | 34 +++++++++++++------ .../core/postoffice/impl/PostOfficeImpl.java | 2 +- .../core/server/impl/ServerSessionImpl.java | 3 +- .../impl/WildcardAddressManagerUnitTest.java | 5 +++ 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/Bindings.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/Bindings.java index 21d37ec02f..07b3f45768 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/Bindings.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/Bindings.java @@ -63,7 +63,5 @@ public interface Bindings extends UnproposalListener { int size(); - default boolean contains(Class clazz) { - return false; - } + boolean hasLocalBinding(); } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/BindingsImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/BindingsImpl.java index a1339a1a77..e3bd6feefb 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/BindingsImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/BindingsImpl.java @@ -52,6 +52,7 @@ import org.apache.activemq.artemis.utils.CompositeAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.invoke.MethodHandles; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.function.BiConsumer; public final class BindingsImpl implements Bindings { @@ -86,7 +87,12 @@ public final class BindingsImpl implements Bindings { /** * This has a version about adds and removes */ - private final AtomicInteger version = new AtomicInteger(sequenceVersion.incrementAndGet()); + private volatile int version; + + private static final AtomicIntegerFieldUpdater VERSION_UPDATER = AtomicIntegerFieldUpdater + .newUpdater(BindingsImpl.class, "version"); + + private volatile boolean hasLocal; public BindingsImpl(final SimpleString name, final GroupingHandler groupingHandler, StorageManager storageManager) { this.groupingHandler = groupingHandler; @@ -157,7 +163,19 @@ public final class BindingsImpl implements Bindings { } private void updated() { - version.set(sequenceVersion.incrementAndGet()); + VERSION_UPDATER.set(this, sequenceVersion.incrementAndGet()); + checkBindingsIdMap(); + } + + private void checkBinding(Long bindingID, Binding binding) { + if (binding instanceof LocalQueueBinding) { + hasLocal = true; + } + } + + private void checkBindingsIdMap() { + hasLocal = false; + bindingsIdMap.forEach(this::checkBinding); } @Override @@ -201,14 +219,8 @@ public final class BindingsImpl implements Bindings { } @Override - public boolean contains(Class clazz) { - for (Binding binding : getBindings()) { - if (clazz.isInstance(binding)) { - return true; - } - } - - return false; + public boolean hasLocalBinding() { + return hasLocal; } @@ -296,7 +308,7 @@ public final class BindingsImpl implements Bindings { private void route(final Message message, final RoutingContext context, final boolean groupRouting) throws Exception { - final int currentVersion = version.get(); + final int currentVersion = VERSION_UPDATER.get(this); final boolean reusableContext = context.isReusable(message, currentVersion); if (!reusableContext) { diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java index f5d6f0ad23..0296594994 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java @@ -1269,7 +1269,7 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding Bindings simpleRoute(SimpleString address, RoutingContext context, Message message, AddressInfo addressInfo) throws Exception { Bindings bindings = addressManager.getBindingsForRoutingAddress(address); - if ((bindings == null || !bindings.contains(LocalQueueBinding.class)) && context.getServerSession() != null) { + if ((bindings == null || !bindings.hasLocalBinding()) && context.getServerSession() != null) { AutoCreateResult autoCreateResult = context.getServerSession().checkAutoCreate(new QueueConfiguration(address).setRoutingType(context.getRoutingType())); if (autoCreateResult == AutoCreateResult.NOT_FOUND) { ActiveMQException e = ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(address); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java index 5b80fcb5b3..d665492d8e 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java @@ -64,7 +64,6 @@ import org.apache.activemq.artemis.core.postoffice.Bindings; import org.apache.activemq.artemis.core.postoffice.PostOffice; import org.apache.activemq.artemis.core.postoffice.QueueBinding; import org.apache.activemq.artemis.core.postoffice.RoutingStatus; -import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.artemis.core.protocol.core.CoreRemotingConnection; import org.apache.activemq.artemis.core.remoting.CertificateUtil; import org.apache.activemq.artemis.core.remoting.CloseListener; @@ -1826,7 +1825,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { if (server.locateQueue(unPrefixedQueue) == null) { // The queue doesn't exist. Bindings bindings = server.getPostOffice().lookupBindingsForAddress(unPrefixedAddress); - if (bindings != null && bindings.contains(LocalQueueBinding.class) && !queueConfig.isFqqn()) { + if (bindings != null && bindings.hasLocalBinding() && !queueConfig.isFqqn()) { // The address has another queue with a different name, which is fine. Just ignore it. result = AutoCreateResult.EXISTED; } else if (addressSettings.isAutoCreateQueues() || queueConfig.isTemporary()) { diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/WildcardAddressManagerUnitTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/WildcardAddressManagerUnitTest.java index a2eace09f5..910704a882 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/WildcardAddressManagerUnitTest.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/WildcardAddressManagerUnitTest.java @@ -493,6 +493,11 @@ public class WildcardAddressManagerUnitTest extends ActiveMQTestBase { this.name = address; } + @Override + public boolean hasLocalBinding() { + return false; + } + @Override public Collection getBindings() { return bindings.values();