Search in sources :

Example 11 with Cache

use of org.jivesoftware.util.cache.Cache in project Openfire by igniterealtime.

the class RoutingTableImpl method restoreCacheContent.

/**
 * When the local node is joining or leaving a cluster, {@link org.jivesoftware.util.cache.CacheFactory} will swap
 * the implementation used to instantiate caches. This causes the cache content to be 'reset': it will no longer
 * contain the data that's provided by the local node. This method restores data that's provided by the local node
 * in the cache. It is expected to be invoked right after joining ({@link #joinedCluster()} or leaving
 * ({@link #leftCluster()} a cluster.
 */
private void restoreCacheContent() {
    Log.debug("Restoring cache content for cache '{}' by adding all outgoing server routes that are connected to the local cluster node.", serversCache.getName());
    // Check if there are local s2s connections that are already in the cache for remote nodes
    Set<DomainPair> localServerRoutesToRemove = new HashSet<>();
    localRoutingTable.getServerRoutes().forEach(route -> route.getOutgoingDomainPairs().forEach(address -> {
        final Lock lock = serversCache.getLock(address);
        lock.lock();
        try {
            if (serversCache.containsKey(address)) {
                Log.info("We have an s2s connection to {}, but this connection also exists on other nodes. They are not allowed to both exist, so this local s2s connection will be terminated.", address);
                localServerRoutesToRemove.add(address);
            } else {
                serversCache.put(address, server.getNodeID());
            }
        } finally {
            lock.unlock();
        }
    }));
    for (DomainPair localServerRouteToRemove : localServerRoutesToRemove) {
        final RoutableChannelHandler route = localRoutingTable.getRoute(localServerRouteToRemove);
        if (route instanceof LocalOutgoingServerSession) {
            // That will result in the s2s connection actually being removed from the LocalRoutingTable.
            try {
                LocalOutgoingServerSession.class.cast(route).close();
            } catch (Exception e) {
                Log.warn("Failed to terminate the local s2s connection for " + localServerRouteToRemove + ".", e);
            }
        } else {
            Log.warn("Failed to terminate the local s2s connection for {} because it is a {} instead of a LocalOutgoingServerSession.", localServerRouteToRemove, route.getClass());
        }
    }
    Log.debug("Restoring cache content for cache '{}' by adding all component routes that are connected to the local cluster node.", componentsCache.getName());
    localRoutingTable.getComponentRoute().forEach(route -> CacheUtil.addValueToMultiValuedCache(componentsCache, route.getAddress().getDomain(), server.getNodeID(), HashSet::new));
    addLocalClientRoutesToCache();
}
Also used : Presence(org.xmpp.packet.Presence) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) Forwarded(org.jivesoftware.openfire.forward.Forwarded) ClientSession(org.jivesoftware.openfire.session.ClientSession) Received(org.jivesoftware.openfire.carbons.Received) BasicModule(org.jivesoftware.openfire.container.BasicModule) CacheFactory(org.jivesoftware.util.cache.CacheFactory) ClusteredCacheEntryListener(org.jivesoftware.openfire.cluster.ClusteredCacheEntryListener) LoggerFactory(org.slf4j.LoggerFactory) JiveGlobals(org.jivesoftware.util.JiveGlobals) MessageRouter(org.jivesoftware.openfire.MessageRouter) ReverseLookupUpdatingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupUpdatingCacheEntryListener) PresenceUpdateHandler(org.jivesoftware.openfire.handler.PresenceUpdateHandler) Message(org.xmpp.packet.Message) OutgoingServerSession(org.jivesoftware.openfire.session.OutgoingServerSession) CacheUtil(org.jivesoftware.util.cache.CacheUtil) RemoteServerManager(org.jivesoftware.openfire.server.RemoteServerManager) Cache(org.jivesoftware.util.cache.Cache) RoutingTable(org.jivesoftware.openfire.RoutingTable) PresenceRouter(org.jivesoftware.openfire.PresenceRouter) ClusterManager(org.jivesoftware.openfire.cluster.ClusterManager) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Collectors(java.util.stream.Collectors) Stream(java.util.stream.Stream) ConnectionSettings(org.jivesoftware.openfire.session.ConnectionSettings) RemoteSessionLocator(org.jivesoftware.openfire.session.RemoteSessionLocator) java.util(java.util) PacketException(org.jivesoftware.openfire.PacketException) Multimap(com.google.common.collect.Multimap) ReverseLookupComputingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupComputingCacheEntryListener) JID(org.xmpp.packet.JID) Function(java.util.function.Function) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) ConcurrentMap(java.util.concurrent.ConcurrentMap) NodeID(org.jivesoftware.openfire.cluster.NodeID) XMPPServer(org.jivesoftware.openfire.XMPPServer) RoutableChannelHandler(org.jivesoftware.openfire.RoutableChannelHandler) RemotePacketRouter(org.jivesoftware.openfire.RemotePacketRouter) ClusterEventListener(org.jivesoftware.openfire.cluster.ClusterEventListener) DomainPair(org.jivesoftware.openfire.session.DomainPair) LocalOutgoingServerSession(org.jivesoftware.openfire.session.LocalOutgoingServerSession) Logger(org.slf4j.Logger) ConsistencyChecks(org.jivesoftware.util.cache.ConsistencyChecks) ExternalComponentManager(org.jivesoftware.openfire.component.ExternalComponentManager) AtomicLong(java.util.concurrent.atomic.AtomicLong) Lock(java.util.concurrent.locks.Lock) Packet(org.xmpp.packet.Packet) OutgoingSessionPromise(org.jivesoftware.openfire.server.OutgoingSessionPromise) Element(org.dom4j.Element) QName(org.dom4j.QName) IQRouter(org.jivesoftware.openfire.IQRouter) IQ(org.xmpp.packet.IQ) LocalOutgoingServerSession(org.jivesoftware.openfire.session.LocalOutgoingServerSession) DomainPair(org.jivesoftware.openfire.session.DomainPair) RoutableChannelHandler(org.jivesoftware.openfire.RoutableChannelHandler) PacketException(org.jivesoftware.openfire.PacketException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) Lock(java.util.concurrent.locks.Lock)

Example 12 with Cache

use of org.jivesoftware.util.cache.Cache in project Openfire by igniterealtime.

the class ClusterListener method addMapListener.

private void addMapListener(Cache cache, MapListener listener) {
    if (cache instanceof CacheWrapper) {
        Cache wrapped = ((CacheWrapper) cache).getWrappedCache();
        if (wrapped instanceof ClusteredCache) {
            ((ClusteredCache) wrapped).addMapListener(listener, new MapEventFilter(MapEventFilter.E_KEYSET), false);
            // Keep track of the listener that we added to the cache
            mapListeners.put(cache, listener);
        }
    }
}
Also used : CacheWrapper(org.jivesoftware.util.cache.CacheWrapper) MapEventFilter(com.tangosol.util.filter.MapEventFilter) Cache(org.jivesoftware.util.cache.Cache)

Example 13 with Cache

use of org.jivesoftware.util.cache.Cache in project Openfire by igniterealtime.

the class ClusterListener method addEntryListener.

private void addEntryListener(Cache cache, EntryListener listener) {
    if (cache instanceof CacheWrapper) {
        Cache wrapped = ((CacheWrapper) cache).getWrappedCache();
        if (wrapped instanceof ClusteredCache) {
            ((ClusteredCache) wrapped).addEntryListener(listener, false);
            // Keep track of the listener that we added to the cache
            EntryListeners.put(cache, listener);
        }
    }
}
Also used : CacheWrapper(org.jivesoftware.util.cache.CacheWrapper) Cache(org.jivesoftware.util.cache.Cache)

Example 14 with Cache

use of org.jivesoftware.util.cache.Cache in project Openfire by igniterealtime.

the class EntityCapabilitiesManager method userDeleting.

@Override
public void userDeleting(User user, Map<String, Object> params) {
    // Delete this user's association in entityCapabilitiesUserMap.
    final JID bareJid = XMPPServer.getInstance().createJID(user.getUsername(), null, true);
    final Set<String> deletedUserVerHashes = new HashSet<>();
    // Remember: Cache's are not regular maps. The EntrySet is immutable.
    // We'll first find the keys, then remove them in a separate call.
    final Lock lock = entityCapabilitiesUserMap.getLock(bareJid);
    lock.lock();
    try {
        // Iterating over the entire set is not ideal from a performance perspective. Note that this is a
        // local cache. Things would have been much worse if this would have been a clustered cache.
        final Set<JID> jidsToRemove = entityCapabilitiesUserMap.keySet().stream().filter(jid -> jid.asBareJID().equals(bareJid)).collect(Collectors.toSet());
        for (final JID jidToRemove : jidsToRemove) {
            final String removed = entityCapabilitiesUserMap.remove(jidToRemove);
            if (removed != null) {
                deletedUserVerHashes.add(removed);
            }
        }
    } finally {
        lock.unlock();
    }
    // If there are no other references to the deleted user's 'ver' hash,
    // it is safe to remove that 'ver' hash's associated entity
    // capabilities from the entityCapabilitiesMap cache.
    deletedUserVerHashes.forEach(this::checkObsolete);
}
Also used : Presence(org.xmpp.packet.Presence) IQResultListener(org.xmpp.component.IQResultListener) java.util(java.util) BasicModule(org.jivesoftware.openfire.container.BasicModule) CacheFactory(org.jivesoftware.util.cache.CacheFactory) LoggerFactory(org.slf4j.LoggerFactory) UserEventDispatcher(org.jivesoftware.openfire.event.UserEventDispatcher) JID(org.xmpp.packet.JID) HashMultimap(com.google.common.collect.HashMultimap) StringUtils(org.jivesoftware.util.StringUtils) UserEventListener(org.jivesoftware.openfire.event.UserEventListener) XMPPServer(org.jivesoftware.openfire.XMPPServer) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) Cache(org.jivesoftware.util.cache.Cache) Logger(org.slf4j.Logger) User(org.jivesoftware.openfire.user.User) CopyOnWriteArraySet(java.util.concurrent.CopyOnWriteArraySet) Collectors(java.util.stream.Collectors) SetMultimap(com.google.common.collect.SetMultimap) Lock(java.util.concurrent.locks.Lock) Element(org.dom4j.Element) QName(org.dom4j.QName) IQRouter(org.jivesoftware.openfire.IQRouter) IQ(org.xmpp.packet.IQ) JID(org.xmpp.packet.JID) Lock(java.util.concurrent.locks.Lock)

Example 15 with Cache

use of org.jivesoftware.util.cache.Cache in project Openfire by igniterealtime.

the class RoutingTableImpl method joinedCluster.

@Override
public void joinedCluster() {
    // The local node joined a cluster.
    // 
    // Upon joining a cluster, clustered caches are reset to their clustered equivalent (by the swap from the local
    // cache implementation to the clustered cache implementation that's done in the implementation of
    // org.jivesoftware.util.cache.CacheFactory.joinedCluster). This means that they now hold data that's
    // available on all other cluster nodes. Data that's available on the local node needs to be added again.
    restoreCacheContent();
    Log.debug("Add the entry listeners to the corresponding caches.");
    // Register a cache entry event listeners that will collect data for entries added by all other cluster nodes,
    // which is intended to be used (only) in the event of a cluster split.
    final ClusteredCacheEntryListener<String, ClientRoute> userCacheEntryListener = new ReverseLookupUpdatingCacheEntryListener<>(routeOwnersByClusterNode);
    final ClusteredCacheEntryListener<DomainPair, NodeID> serversCacheEntryListener = new ReverseLookupUpdatingCacheEntryListener<>(s2sDomainPairsByClusterNode);
    final ClusteredCacheEntryListener<String, HashSet<NodeID>> componentsCacheEntryListener = new ReverseLookupComputingCacheEntryListener<>(componentsByClusterNode, nodeIDS -> nodeIDS.stream().filter(n -> !n.equals(XMPPServer.getInstance().getNodeID())).collect(Collectors.toSet()));
    // Note that, when #joinedCluster() fired, the cache will _always_ have been replaced, meaning that it won't
    // have old event listeners. When #leaveCluster() fires, the cache will be destroyed. This takes away the need
    // to explicitly deregister the listener in that case.
    // Ensure that event listeners have been registered with the caches, before starting to simulate 'entryAdded' events,
    // to prevent the possibility of having entries that are missed by the simulation because of bad timing.
    usersCache.addClusteredCacheEntryListener(userCacheEntryListener, false, false);
    anonymousUsersCache.addClusteredCacheEntryListener(userCacheEntryListener, false, false);
    serversCache.addClusteredCacheEntryListener(serversCacheEntryListener, false, false);
    componentsCache.addClusteredCacheEntryListener(componentsCacheEntryListener, true, true);
    // This is not necessary for the usersSessions cache, because its content is being managed while the content
    // of users cache and anonymous users cache is being managed.
    Log.debug("Simulate 'entryAdded' for all data that already exists elsewhere in the cluster.");
    Stream.concat(usersCache.entrySet().stream(), anonymousUsersCache.entrySet().stream()).filter(entry -> !entry.getValue().getNodeID().equals(XMPPServer.getInstance().getNodeID())).forEach(entry -> userCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), entry.getValue().getNodeID()));
    serversCache.entrySet().stream().filter(entry -> !entry.getValue().equals(XMPPServer.getInstance().getNodeID())).forEach(entry -> serversCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), entry.getValue()));
    componentsCache.entrySet().forEach(entry -> {
        entry.getValue().forEach(nodeIdForComponent -> {
            // Iterate over all node ids on which the component is known
            if (!nodeIdForComponent.equals(XMPPServer.getInstance().getNodeID())) {
                // Here we pretend that the component has been added by the node id on which it is reported to
                // be available. This might not have been the case, but it is probably accurate. An alternative
                // approach is not easily available.
                componentsCacheEntryListener.entryAdded(entry.getKey(), entry.getValue(), nodeIdForComponent);
            }
        });
    });
    // Broadcast presence of local sessions to remote sessions when subscribed to presence.
    // Probe presences of remote sessions when subscribed to presence of local session.
    // Send pending subscription requests to local sessions from remote sessions.
    // Deliver offline messages sent to local sessions that were unavailable in other nodes.
    // Send available presences of local sessions to other resources of the same user.
    PresenceUpdateHandler presenceUpdateHandler = XMPPServer.getInstance().getPresenceUpdateHandler();
    for (LocalClientSession session : localRoutingTable.getClientRoutes()) {
        // Simulate that the local session has just become available
        session.setInitialized(false);
        // Simulate that current session presence has just been received
        presenceUpdateHandler.process(session.getPresence());
    }
// TODO OF-2067: the above also (re)generates events on the local node, where these events had already occurred. Ideally, that should not happen.
// TODO OF-2066: shouldn't a similar action be done on the other nodes, so that the node that just joined gets informed about all sessions living on other cluster nodes?
}
Also used : Presence(org.xmpp.packet.Presence) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) Forwarded(org.jivesoftware.openfire.forward.Forwarded) ClientSession(org.jivesoftware.openfire.session.ClientSession) Received(org.jivesoftware.openfire.carbons.Received) BasicModule(org.jivesoftware.openfire.container.BasicModule) CacheFactory(org.jivesoftware.util.cache.CacheFactory) ClusteredCacheEntryListener(org.jivesoftware.openfire.cluster.ClusteredCacheEntryListener) LoggerFactory(org.slf4j.LoggerFactory) JiveGlobals(org.jivesoftware.util.JiveGlobals) MessageRouter(org.jivesoftware.openfire.MessageRouter) ReverseLookupUpdatingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupUpdatingCacheEntryListener) PresenceUpdateHandler(org.jivesoftware.openfire.handler.PresenceUpdateHandler) Message(org.xmpp.packet.Message) OutgoingServerSession(org.jivesoftware.openfire.session.OutgoingServerSession) CacheUtil(org.jivesoftware.util.cache.CacheUtil) RemoteServerManager(org.jivesoftware.openfire.server.RemoteServerManager) Cache(org.jivesoftware.util.cache.Cache) RoutingTable(org.jivesoftware.openfire.RoutingTable) PresenceRouter(org.jivesoftware.openfire.PresenceRouter) ClusterManager(org.jivesoftware.openfire.cluster.ClusterManager) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Collectors(java.util.stream.Collectors) Stream(java.util.stream.Stream) ConnectionSettings(org.jivesoftware.openfire.session.ConnectionSettings) RemoteSessionLocator(org.jivesoftware.openfire.session.RemoteSessionLocator) java.util(java.util) PacketException(org.jivesoftware.openfire.PacketException) Multimap(com.google.common.collect.Multimap) ReverseLookupComputingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupComputingCacheEntryListener) JID(org.xmpp.packet.JID) Function(java.util.function.Function) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) ConcurrentMap(java.util.concurrent.ConcurrentMap) NodeID(org.jivesoftware.openfire.cluster.NodeID) XMPPServer(org.jivesoftware.openfire.XMPPServer) RoutableChannelHandler(org.jivesoftware.openfire.RoutableChannelHandler) RemotePacketRouter(org.jivesoftware.openfire.RemotePacketRouter) ClusterEventListener(org.jivesoftware.openfire.cluster.ClusterEventListener) DomainPair(org.jivesoftware.openfire.session.DomainPair) LocalOutgoingServerSession(org.jivesoftware.openfire.session.LocalOutgoingServerSession) Logger(org.slf4j.Logger) ConsistencyChecks(org.jivesoftware.util.cache.ConsistencyChecks) ExternalComponentManager(org.jivesoftware.openfire.component.ExternalComponentManager) AtomicLong(java.util.concurrent.atomic.AtomicLong) Lock(java.util.concurrent.locks.Lock) Packet(org.xmpp.packet.Packet) OutgoingSessionPromise(org.jivesoftware.openfire.server.OutgoingSessionPromise) Element(org.dom4j.Element) QName(org.dom4j.QName) IQRouter(org.jivesoftware.openfire.IQRouter) IQ(org.xmpp.packet.IQ) ReverseLookupUpdatingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupUpdatingCacheEntryListener) PresenceUpdateHandler(org.jivesoftware.openfire.handler.PresenceUpdateHandler) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) DomainPair(org.jivesoftware.openfire.session.DomainPair) NodeID(org.jivesoftware.openfire.cluster.NodeID) ReverseLookupComputingCacheEntryListener(org.jivesoftware.util.cache.ReverseLookupComputingCacheEntryListener)

Aggregations

Cache (org.jivesoftware.util.cache.Cache)19 CacheFactory (org.jivesoftware.util.cache.CacheFactory)11 Logger (org.slf4j.Logger)11 LoggerFactory (org.slf4j.LoggerFactory)11 JID (org.xmpp.packet.JID)11 java.util (java.util)10 Lock (java.util.concurrent.locks.Lock)10 Collectors (java.util.stream.Collectors)10 Presence (org.xmpp.packet.Presence)10 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)9 XMPPServer (org.jivesoftware.openfire.XMPPServer)9 ClusterManager (org.jivesoftware.openfire.cluster.ClusterManager)9 NodeID (org.jivesoftware.openfire.cluster.NodeID)9 Element (org.dom4j.Element)8 RoutingTable (org.jivesoftware.openfire.RoutingTable)8 ClusterEventListener (org.jivesoftware.openfire.cluster.ClusterEventListener)8 Packet (org.xmpp.packet.Packet)8 QName (org.dom4j.QName)7 PacketException (org.jivesoftware.openfire.PacketException)7 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)7