private void restoreCacheContent() {
        Log.trace( "Restoring cache content for cache '{}' by adding all directed presences that are provided by the local cluster node.", directedPresencesCache.getName() );

        // Populate directedPresencesCache with local content since when not in a cluster
        // we could still send directed presences to entities that when connected to a cluster
        // they will be replicated. An example would be MUC rooms.
        for (Map.Entry<String, ConcurrentLinkedQueue<DirectedPresence>> entry : localDirectedPresences.entrySet()) {
            if (entry.getValue().isEmpty()) {
                Log.warn("Skipping empty directed presences when joining cluster for sender: {}", entry.getKey());
                continue;
            }

            // TODO perhaps we should not lock for every entry. Instead, lock it
            // once (using a LOCK_ALL global key), and handle iterations in
            // one go. We should first make sure that this doesn't lead to
            // deadlocks though! The tryLock() mechanism could be used to first
            // try one approach, but fall back on the other approach.
            Lock lock = directedPresencesCache.getLock(entry.getKey());
            lock.lock();
            try {
                directedPresencesCache.put(entry.getKey(), entry.getValue());
            } finally {
                lock.unlock();
            }
        }

    }
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.
xmppserver/src/main/java/org/jivesoftware/openfire/handler/PresenceUpdateHandler.java