[disco] Delay the entity caps renewal

This avoids the calculation of the caps hash while the managers become
registered with the connection and add their features.
This commit is contained in:
Florian Schmaus 2020-05-16 21:19:06 +02:00
parent 72c5dc5886
commit 46ba273689
2 changed files with 59 additions and 4 deletions

View File

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.disco; package org.jivesoftware.smackx.disco;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -28,20 +29,25 @@ import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.ScheduledAction;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.internal.AbstractStats;
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode; import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smack.util.CollectionUtil; import org.jivesoftware.smack.util.CollectionUtil;
import org.jivesoftware.smack.util.ExtendedAppendable;
import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
@ -894,13 +900,33 @@ public final class ServiceDiscoveryManager extends Manager {
return entityCapabilitiesChangedListeners.add(entityCapabilitiesChangedListener); return entityCapabilitiesChangedListeners.add(entityCapabilitiesChangedListener);
} }
private static final int RENEW_ENTITY_CAPS_DELAY_MILLIS = 25;
private ScheduledAction renewEntityCapsScheduledAction;
private final AtomicInteger renewEntityCapsPerformed = new AtomicInteger();
private int renewEntityCapsRequested = 0;
private int scheduledRenewEntityCapsAvoided = 0;
/** /**
* Notify the {@link EntityCapabilitiesChangedListener} about changed capabilities. * Notify the {@link EntityCapabilitiesChangedListener} about changed capabilities.
*/ */
private void renewEntityCapsVersion() { private synchronized void renewEntityCapsVersion() {
for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) { renewEntityCapsRequested++;
entityCapabilitiesChangedListener.onEntityCapailitiesChanged(); if (renewEntityCapsScheduledAction != null) {
boolean canceled = renewEntityCapsScheduledAction.cancel();
if (canceled) {
scheduledRenewEntityCapsAvoided++;
}
} }
renewEntityCapsScheduledAction = scheduleBlocking(() -> {
renewEntityCapsPerformed.incrementAndGet();
for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) {
entityCapabilitiesChangedListener.onEntityCapailitiesChanged();
}
}, RENEW_ENTITY_CAPS_DELAY_MILLIS, TimeUnit.MILLISECONDS);
} }
public static void addDiscoInfoLookupShortcutMechanism(DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism) { public static void addDiscoInfoLookupShortcutMechanism(DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism) {
@ -915,4 +941,30 @@ public final class ServiceDiscoveryManager extends Manager {
discoInfoLookupShortcutMechanisms.remove(discoInfoLookupShortcutMechanism); discoInfoLookupShortcutMechanisms.remove(discoInfoLookupShortcutMechanism);
} }
} }
public synchronized Stats getStats() {
return new Stats(this);
}
public static final class Stats extends AbstractStats {
public final int renewEntityCapsRequested;
public final int renewEntityCapsPerformed;
public final int scheduledRenewEntityCapsAvoided;
private Stats(ServiceDiscoveryManager serviceDiscoveryManager) {
renewEntityCapsRequested = serviceDiscoveryManager.renewEntityCapsRequested;
renewEntityCapsPerformed = serviceDiscoveryManager.renewEntityCapsPerformed.get();
scheduledRenewEntityCapsAvoided = serviceDiscoveryManager.scheduledRenewEntityCapsAvoided;
}
@Override
public void appendStatsTo(ExtendedAppendable appendable) throws IOException {
StringUtils.appendHeading(appendable, "ServiceDiscoveryManager stats", '#').append('\n');
appendable.append("renew-entitycaps-requested: ").append(renewEntityCapsRequested).append('\n');
appendable.append("renew-entitycaps-performed: ").append(renewEntityCapsPerformed).append('\n');
appendable.append("scheduled-renew-entitycaps-avoided: ").append(scheduledRenewEntityCapsAvoided).append('\n');
}
}
} }

View File

@ -42,6 +42,8 @@ import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.sm.StreamManagementModuleDescriptor; import org.jivesoftware.smack.sm.StreamManagementModuleDescriptor;
import org.jivesoftware.smack.tcp.XmppTcpTransportModuleDescriptor; import org.jivesoftware.smack.tcp.XmppTcpTransportModuleDescriptor;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jxmpp.util.XmppDateTime; import org.jxmpp.util.XmppDateTime;
public class Nio { public class Nio {
@ -128,9 +130,10 @@ public class Nio {
connection.disconnect(); connection.disconnect();
ModularXmppClientToServerConnection.Stats connectionStats = connection.getStats(); ModularXmppClientToServerConnection.Stats connectionStats = connection.getStats();
ServiceDiscoveryManager.Stats serviceDiscoveryManagerStats = ServiceDiscoveryManager.getInstanceFor(connection).getStats();
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
System.out.println("NIO successfully finished, yeah!\n" + connectionStats); System.out.println("NIO successfully finished, yeah!\n" + connectionStats + '\n' + serviceDiscoveryManagerStats);
// CHECKSTYLE:ON // CHECKSTYLE:ON
} }