public static Multimap<String, String> generateReportForUserSessions(
        @Nonnull final Cache<String, HashSet<String>> usersSessionsCache,
        @Nonnull final Cache<String, ClientRoute> usersCache
    ) {
        // Take snapshots of all data structures at as much the same time as possible.
        final ConcurrentMap<String, HashSet<String>> cache = new ConcurrentHashMap<>(usersSessionsCache);
        final Set<String> usersCacheKeys = usersCache.keySet();

        final Set<String> userCacheKeysNotInSessionsCache = usersCacheKeys.stream()
            .filter(fullJid -> {
                HashSet<String> fullJids = cache.get(new JID(fullJid).toBareJID());
                return fullJids == null || !fullJids.contains(fullJid);
            })
            .collect(Collectors.toSet());

        final Set<String> sessionCacheItemsNotInUserCache = cache.values().stream()
            .flatMap(HashSet::stream)
            .filter(fullJid -> !usersCacheKeys.contains(fullJid))
            .collect(Collectors.toSet());

        // Generate report
        final Multimap<String, String> result = HashMultimap.create();

        result.put("info", String.format("The cache named %s is used to share data in the cluster, which contains %d session infos.", usersSessionsCache.getName(), cache.size()));

        result.put("data", String.format("%s contains these entries (these are shared in the cluster):\n%s", usersSessionsCache.getName(), cache.entrySet()
            .stream()
            .map(e -> e.getKey() + " -> " + e.getValue())
            .sorted()
            .collect(Collectors.joining("\n"))));
        result.put("data", String.format("%s contains these entries (these are shared in the cluster):\n%s", usersCache.getName(), usersCacheKeys.stream().sorted()
            .collect(Collectors.joining("\n"))));

        if (userCacheKeysNotInSessionsCache.isEmpty()) {
            result.put("pass", "All user cache entries exist in the user sessions cache.");
        } else {
            result.put("fail", String.format("User sessions cache is missing entries that are present in the user cache. These %d entries are missing: %s", userCacheKeysNotInSessionsCache.size(), String.join(", ", userCacheKeysNotInSessionsCache)));
        }

        if (sessionCacheItemsNotInUserCache.isEmpty()) {
            result.put("pass", "All user sessions cache entries exist in the user cache.");
        } else {
            result.put("fail", String.format("User cache is missing entries that are present in the user sessions cache. These %d entries are missing: %s", sessionCacheItemsNotInUserCache.size(), String.join(", ", sessionCacheItemsNotInUserCache)));
        }

        return result;
    }
Verifies that #sessionInfoCache, #localSessionInfos and #sessionInfoKeysByClusterNode
of {@link org.jivesoftware.openfire.SessionManager} are in a consistent state.
<p>
Note that this operation can be costly in terms of resource usage. Use with caution in large / busy systems.
<p>
The returned multi-map can contain up to four keys: info, fail, pass, data. All entry values are a human readable
description of a checked characteristic. When the state is consistent, no 'fail' entries will be returned.

@param sessionInfoCache             The cache that is used to share data across cluster nodes. (note that unlike its siblings, this is empty when not clustering!)
@param localSessions                The data structure that keeps track of what data was added to the cache by the local cluster node.
@param sessionInfoKeysByClusterNode The data structure that keeps track of what data was added to the cache by the remote cluster nodes.
@return A consistency state report.
xmppserver/src/main/java/org/jivesoftware/util/cache/ConsistencyChecks.java