ARTEMIS-4450 Caching hasLocal boolean on bindings to avoid transversing the maps on every call

This commit is contained in:
Clebert Suconic 2023-10-05 11:43:35 -04:00 committed by clebertsuconic
parent 4db39520f2
commit 42be518deb
5 changed files with 31 additions and 17 deletions

View File

@ -63,7 +63,5 @@ public interface Bindings extends UnproposalListener {
int size(); int size();
default boolean contains(Class clazz) { boolean hasLocalBinding();
return false;
}
} }

View File

@ -52,6 +52,7 @@ import org.apache.activemq.artemis.utils.CompositeAddress;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public final class BindingsImpl implements Bindings { public final class BindingsImpl implements Bindings {
@ -86,7 +87,12 @@ public final class BindingsImpl implements Bindings {
/** /**
* This has a version about adds and removes * This has a version about adds and removes
*/ */
private final AtomicInteger version = new AtomicInteger(sequenceVersion.incrementAndGet()); private volatile int version;
private static final AtomicIntegerFieldUpdater<BindingsImpl> VERSION_UPDATER = AtomicIntegerFieldUpdater
.newUpdater(BindingsImpl.class, "version");
private volatile boolean hasLocal;
public BindingsImpl(final SimpleString name, final GroupingHandler groupingHandler, StorageManager storageManager) { public BindingsImpl(final SimpleString name, final GroupingHandler groupingHandler, StorageManager storageManager) {
this.groupingHandler = groupingHandler; this.groupingHandler = groupingHandler;
@ -157,7 +163,19 @@ public final class BindingsImpl implements Bindings {
} }
private void updated() { 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 @Override
@ -201,14 +219,8 @@ public final class BindingsImpl implements Bindings {
} }
@Override @Override
public boolean contains(Class clazz) { public boolean hasLocalBinding() {
for (Binding binding : getBindings()) { return hasLocal;
if (clazz.isInstance(binding)) {
return true;
}
}
return false;
} }
@ -296,7 +308,7 @@ public final class BindingsImpl implements Bindings {
private void route(final Message message, private void route(final Message message,
final RoutingContext context, final RoutingContext context,
final boolean groupRouting) throws Exception { final boolean groupRouting) throws Exception {
final int currentVersion = version.get(); final int currentVersion = VERSION_UPDATER.get(this);
final boolean reusableContext = context.isReusable(message, currentVersion); final boolean reusableContext = context.isReusable(message, currentVersion);
if (!reusableContext) { if (!reusableContext) {

View File

@ -1269,7 +1269,7 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
Bindings simpleRoute(SimpleString address, RoutingContext context, Message message, AddressInfo addressInfo) throws Exception { Bindings simpleRoute(SimpleString address, RoutingContext context, Message message, AddressInfo addressInfo) throws Exception {
Bindings bindings = addressManager.getBindingsForRoutingAddress(address); 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())); AutoCreateResult autoCreateResult = context.getServerSession().checkAutoCreate(new QueueConfiguration(address).setRoutingType(context.getRoutingType()));
if (autoCreateResult == AutoCreateResult.NOT_FOUND) { if (autoCreateResult == AutoCreateResult.NOT_FOUND) {
ActiveMQException e = ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(address); ActiveMQException e = ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(address);

View File

@ -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.PostOffice;
import org.apache.activemq.artemis.core.postoffice.QueueBinding; import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.postoffice.RoutingStatus; 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.protocol.core.CoreRemotingConnection;
import org.apache.activemq.artemis.core.remoting.CertificateUtil; import org.apache.activemq.artemis.core.remoting.CertificateUtil;
import org.apache.activemq.artemis.core.remoting.CloseListener; import org.apache.activemq.artemis.core.remoting.CloseListener;
@ -1826,7 +1825,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
if (server.locateQueue(unPrefixedQueue) == null) { if (server.locateQueue(unPrefixedQueue) == null) {
// The queue doesn't exist. // The queue doesn't exist.
Bindings bindings = server.getPostOffice().lookupBindingsForAddress(unPrefixedAddress); 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. // The address has another queue with a different name, which is fine. Just ignore it.
result = AutoCreateResult.EXISTED; result = AutoCreateResult.EXISTED;
} else if (addressSettings.isAutoCreateQueues() || queueConfig.isTemporary()) { } else if (addressSettings.isAutoCreateQueues() || queueConfig.isTemporary()) {

View File

@ -493,6 +493,11 @@ public class WildcardAddressManagerUnitTest extends ActiveMQTestBase {
this.name = address; this.name = address;
} }
@Override
public boolean hasLocalBinding() {
return false;
}
@Override @Override
public Collection<Binding> getBindings() { public Collection<Binding> getBindings() {
return bindings.values(); return bindings.values();