Commit 8f1c7a06 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Caches defined by plugins can now be loaded/unloaded/shared between cluster nodes.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9505 b35dd754-fafc-0310-a699-88a17e54d16e
parent 2669e450
...@@ -11,15 +11,15 @@ ...@@ -11,15 +11,15 @@
package org.jivesoftware.openfire.container; package org.jivesoftware.openfire.container;
import org.dom4j.io.SAXReader;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
/** /**
* A helper class to read cache configuration data for a plugin and register the defined caches with * A helper class to read cache configuration data for a plugin and register the defined caches with
...@@ -82,12 +82,12 @@ public class PluginCacheConfigurator { ...@@ -82,12 +82,12 @@ public class PluginCacheConfigurator {
Map<String, String> initParams = readInitParams(configData); Map<String, String> initParams = readInitParams(configData);
CacheInfo info = new CacheInfo(cacheName, CacheInfo.Type.valueof(schemeName), initParams); CacheInfo info = new CacheInfo(cacheName, CacheInfo.Type.valueof(schemeName), initParams);
PluginCacheRegistry.registerCache(pluginName, info); PluginCacheRegistry.getInstance().registerCache(pluginName, info);
} }
private Map<String, String> readInitParams(Node configData) { private Map<String, String> readInitParams(Node configData) {
Map<String, String> paramMap = new HashMap<String, String>(); Map<String, String> paramMap = new HashMap<String, String>();
List<Node> params = configData.selectNodes("//init-param"); List<Node> params = configData.selectNodes("init-params/init-param");
for (Node param : params) { for (Node param : params) {
String paramName = param.selectSingleNode("param-name").getStringValue(); String paramName = param.selectSingleNode("param-name").getStringValue();
String paramValue = param.selectSingleNode("param-value").getStringValue(); String paramValue = param.selectSingleNode("param-value").getStringValue();
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
package org.jivesoftware.openfire.container; package org.jivesoftware.openfire.container;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.util.cache.CacheFactory; import org.jivesoftware.util.cache.CacheFactory;
...@@ -23,9 +24,17 @@ import java.util.Map; ...@@ -23,9 +24,17 @@ import java.util.Map;
* A simple registry of cache configuration data for plugins. * A simple registry of cache configuration data for plugins.
*/ */
public class PluginCacheRegistry { public class PluginCacheRegistry {
private static final PluginCacheRegistry instance = new PluginCacheRegistry();
private static Map<String, CacheInfo> extraCacheMappings = new HashMap<String, CacheInfo>(); private Map<String, CacheInfo> extraCacheMappings = new HashMap<String, CacheInfo>();
private static Map<String, List<CacheInfo>> pluginCaches = new HashMap<String, List<CacheInfo>>(); private Map<String, List<CacheInfo>> pluginCaches = new HashMap<String, List<CacheInfo>>();
public static PluginCacheRegistry getInstance() {
return instance;
}
private PluginCacheRegistry() {
}
/** /**
* Registers cache configuration data for a give cache and plugin. * Registers cache configuration data for a give cache and plugin.
...@@ -33,7 +42,7 @@ public class PluginCacheRegistry { ...@@ -33,7 +42,7 @@ public class PluginCacheRegistry {
* @param pluginName the name of the plugin which will use the cache. * @param pluginName the name of the plugin which will use the cache.
* @param info the cache configuration data. * @param info the cache configuration data.
*/ */
public static void registerCache(String pluginName, CacheInfo info) { public void registerCache(String pluginName, CacheInfo info) {
extraCacheMappings.put(info.getCacheName(), info); extraCacheMappings.put(info.getCacheName(), info);
List<CacheInfo> caches = pluginCaches.get(pluginName); List<CacheInfo> caches = pluginCaches.get(pluginName);
...@@ -43,6 +52,12 @@ public class PluginCacheRegistry { ...@@ -43,6 +52,12 @@ public class PluginCacheRegistry {
} }
caches.add(info); caches.add(info);
// Set system properties for this cache
CacheFactory.setCacheTypeProperty(info.getCacheName(), info.getType().getName());
CacheFactory.setMaxSizeProperty(info.getCacheName(), getMaxSizeFromProperty(info));
CacheFactory.setMaxLifetimeProperty(info.getCacheName(), getMaxLifetimeFromProperty(info));
CacheFactory.setMinCacheSize(info.getCacheName(), getMinSizeFromProperty(info));
} }
/** /**
...@@ -50,12 +65,13 @@ public class PluginCacheRegistry { ...@@ -50,12 +65,13 @@ public class PluginCacheRegistry {
* *
* @param pluginName the name of the plugin whose caches will be unregistered. * @param pluginName the name of the plugin whose caches will be unregistered.
*/ */
public static void unregisterCaches(String pluginName) { public void unregisterCaches(String pluginName) {
List<CacheInfo> caches = pluginCaches.remove(pluginName); List<CacheInfo> caches = pluginCaches.remove(pluginName);
if (caches != null) { if (caches != null) {
for (CacheInfo info : caches) { for (CacheInfo info : caches) {
extraCacheMappings.remove(info.getCacheName()); extraCacheMappings.remove(info.getCacheName());
try { try {
// TODO Destroy cache if we are the last node hosting this plugin
CacheFactory.destroyCache(info.getCacheName()); CacheFactory.destroyCache(info.getCacheName());
} }
catch (Exception e) { catch (Exception e) {
...@@ -65,7 +81,68 @@ public class PluginCacheRegistry { ...@@ -65,7 +81,68 @@ public class PluginCacheRegistry {
} }
} }
public static CacheInfo getCacheInfo(String name) { public CacheInfo getCacheInfo(String name) {
return extraCacheMappings.get(name); return extraCacheMappings.get(name);
} }
private long getMaxSizeFromProperty(CacheInfo cacheInfo) {
String sizeProp = cacheInfo.getParams().get("back-size-high");
if (sizeProp != null) {
if ("0".equals(sizeProp)) {
return -1l;
}
try {
return Integer.parseInt(sizeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse back-size-high for cache: " + cacheInfo.getCacheName());
}
}
// Return default
return CacheFactory.DEFAULT_MAX_CACHE_SIZE;
}
private static long getMaxLifetimeFromProperty(CacheInfo cacheInfo) {
String lifetimeProp = cacheInfo.getParams().get("back-expiry");
if (lifetimeProp != null) {
if ("0".equals(lifetimeProp)) {
return -1l;
}
long factor = 1;
if (lifetimeProp.endsWith("m")) {
factor = JiveConstants.MINUTE;
}
else if (lifetimeProp.endsWith("h")) {
factor = JiveConstants.HOUR;
}
else if (lifetimeProp.endsWith("d")) {
factor = JiveConstants.DAY;
}
try {
return Long.parseLong(lifetimeProp.substring(0, lifetimeProp.length()-1)) * factor;
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse back-expiry for cache: " + cacheInfo.getCacheName());
}
}
// Return default
return CacheFactory.DEFAULT_MAX_CACHE_LIFETIME;
}
private long getMinSizeFromProperty(CacheInfo cacheInfo) {
String sizeProp = cacheInfo.getParams().get("back-size-low");
if (sizeProp != null) {
if ("0".equals(sizeProp)) {
return -1l;
}
try {
return Integer.parseInt(sizeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse back-size-low for cache: " + cacheInfo.getCacheName());
}
}
// Return default
return CacheFactory.DEFAULT_MAX_CACHE_SIZE;
}
} }
...@@ -610,7 +610,7 @@ public class PluginManager { ...@@ -610,7 +610,7 @@ public class PluginManager {
if (plugin != null && !dir.exists()) { if (plugin != null && !dir.exists()) {
// Unregister plugin caches // Unregister plugin caches
PluginCacheRegistry.unregisterCaches(pluginName); PluginCacheRegistry.getInstance().unregisterCaches(pluginName);
plugins.remove(pluginName); plugins.remove(pluginName);
pluginDirs.remove(plugin); pluginDirs.remove(plugin);
......
...@@ -16,13 +16,11 @@ import org.jivesoftware.openfire.container.Plugin; ...@@ -16,13 +16,11 @@ import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginClassLoader; import org.jivesoftware.openfire.container.PluginClassLoader;
import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.util.InitializationException; import org.jivesoftware.util.InitializationException;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
...@@ -52,16 +50,248 @@ public class CacheFactory { ...@@ -52,16 +50,248 @@ public class CacheFactory {
private static CacheFactoryStrategy cacheFactoryStrategy; private static CacheFactoryStrategy cacheFactoryStrategy;
private static Thread statsThread; private static Thread statsThread;
public static final int DEFAULT_MAX_CACHE_SIZE = 1024 * 256;
public static final long DEFAULT_MAX_CACHE_LIFETIME = 6 * JiveConstants.HOUR;
/**
* This map contains property names which were used to store cache configuration data
* in local xml properties in previous versions.
*/
private static final Map<String, String> cacheNames = new HashMap<String, String>();
/**
* Default properties to use for local caches. Default properties can be overridden
* by setting the corresponding system properties.
*/
private static final Map<String, Long> cacheProps = new HashMap<String, Long>();
static { static {
localCacheFactoryClass = JiveGlobals.getProperty(LOCAL_CACHE_PROPERTY_NAME, localCacheFactoryClass = JiveGlobals.getProperty(LOCAL_CACHE_PROPERTY_NAME,
"org.jivesoftware.util.cache.DefaultLocalCacheStrategy"); "org.jivesoftware.util.cache.DefaultLocalCacheStrategy");
clusteredCacheFactoryClass = JiveGlobals.getProperty(CLUSTERED_CACHE_PROPERTY_NAME, clusteredCacheFactoryClass = JiveGlobals.getProperty(CLUSTERED_CACHE_PROPERTY_NAME,
"com.jivesoftware.util.cache.CoherenceClusteredCacheFactory"); "com.jivesoftware.util.cache.CoherenceClusteredCacheFactory");
cacheNames.put("Favicon Hits", "faviconHits");
cacheNames.put("Favicon Misses", "faviconMisses");
cacheNames.put("Group", "group");
cacheNames.put("Group Metadata Cache", "groupMeta");
cacheNames.put("Javascript Cache", "javascript");
cacheNames.put("Last Activity Cache", "lastActivity");
cacheNames.put("Multicast Service", "multicast");
cacheNames.put("Offline Message Size", "offlinemessage");
cacheNames.put("Offline Presence Cache", "offlinePresence");
cacheNames.put("Privacy Lists", "listsCache");
cacheNames.put("Remote Users Existence", "remoteUsersCache");
cacheNames.put("Roster", "username2roster");
cacheNames.put("User", "userCache");
cacheNames.put("VCard", "vcardCache");
cacheNames.put("File Transfer Cache", "fileTransfer");
cacheNames.put("File Transfer", "transferProxy");
cacheNames.put("POP3 Authentication", "pop3");
cacheNames.put("LDAP Authentication", "ldap");
cacheNames.put("Routing Servers Cache", "routeServer");
cacheNames.put("Routing Components Cache", "routeComponent");
cacheNames.put("Routing Users Cache", "routeUser");
cacheNames.put("Routing AnonymousUsers Cache", "routeAnonymousUser");
cacheNames.put("Routing User Sessions", "routeUserSessions");
cacheNames.put("Components Sessions", "componentsSessions");
cacheNames.put("Connection Managers Sessions", "connManagerSessions");
cacheNames.put("Incoming Server Sessions", "incServerSessions");
cacheNames.put("Sessions by Hostname", "sessionsHostname");
cacheNames.put("Secret Keys Cache", "secretKeys");
cacheNames.put("Validated Domains", "validatedDomains");
cacheNames.put("Directed Presences", "directedPresences");
cacheNames.put("Disco Server Features", "serverFeatures");
cacheNames.put("Disco Server Items", "serverItems");
cacheNames.put("Remote Server Configurations", "serversConfigurations");
cacheNames.put("Entity Capabilities", "entityCapabilities");
cacheNames.put("Entity Capabilities Users", "entityCapabilitiesUsers");
cacheNames.put("Entity Capabilities Pending Hashes", "entityCapabilitiesPendingHashes");
cacheProps.put("cache.fileTransfer.size", 128 * 1024l);
cacheProps.put("cache.fileTransfer.maxLifetime", 1000 * 60 * 10l);
cacheProps.put("cache.multicast.size", 128 * 1024l);
cacheProps.put("cache.multicast.maxLifetime", JiveConstants.DAY);
cacheProps.put("cache.offlinemessage.size", 100 * 1024l);
cacheProps.put("cache.offlinemessage.maxLifetime", JiveConstants.HOUR * 12);
cacheProps.put("cache.pop3.size", 512 * 1024l);
cacheProps.put("cache.pop3.maxLifetime", JiveConstants.HOUR);
cacheProps.put("cache.transferProxy.size", -1l);
cacheProps.put("cache.transferProxy.maxLifetime", 1000 * 60 * 10l);
cacheProps.put("cache.group.size", 1024 * 1024l);
cacheProps.put("cache.group.maxLifetime", JiveConstants.MINUTE * 15);
cacheProps.put("cache.groupMeta.size", 512 * 1024l);
cacheProps.put("cache.groupMeta.maxLifetime", JiveConstants.MINUTE * 15);
cacheProps.put("cache.javascript.size", 128 * 1024l);
cacheProps.put("cache.javascript.maxLifetime", 3600 * 24 * 10l);
cacheProps.put("cache.ldap.size", 512 * 1024l);
cacheProps.put("cache.ldap.maxLifetime", JiveConstants.HOUR * 2);
cacheProps.put("cache.listsCache.size", 512 * 1024l);
cacheProps.put("cache.offlinePresence.size", 512 * 1024l);
cacheProps.put("cache.lastActivity.size", 128 * 1024l);
cacheProps.put("cache.userCache.size", 512 * 1024l);
cacheProps.put("cache.userCache.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.remoteUsersCache.size", 512 * 1024l);
cacheProps.put("cache.remoteUsersCache.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.vcardCache.size", 512 * 1024l);
cacheProps.put("cache.faviconHits.size", 128 * 1024l);
cacheProps.put("cache.faviconMisses.size", 128 * 1024l);
cacheProps.put("cache.routeServer.size", -1l);
cacheProps.put("cache.routeServer.maxLifetime", -1l);
cacheProps.put("cache.routeComponent.size", -1l);
cacheProps.put("cache.routeComponent.maxLifetime", -1l);
cacheProps.put("cache.routeUser.size", -1l);
cacheProps.put("cache.routeUser.maxLifetime", -1l);
cacheProps.put("cache.routeAnonymousUser.size", -1l);
cacheProps.put("cache.routeAnonymousUser.maxLifetime", -1l);
cacheProps.put("cache.routeUserSessions.size", -1l);
cacheProps.put("cache.routeUserSessions.maxLifetime", -1l);
cacheProps.put("cache.componentsSessions.size", -1l);
cacheProps.put("cache.componentsSessions.maxLifetime", -1l);
cacheProps.put("cache.connManagerSessions.size", -1l);
cacheProps.put("cache.connManagerSessions.maxLifetime", -1l);
cacheProps.put("cache.incServerSessions.size", -1l);
cacheProps.put("cache.incServerSessions.maxLifetime", -1l);
cacheProps.put("cache.sessionsHostname.size", -1l);
cacheProps.put("cache.sessionsHostname.maxLifetime", -1l);
cacheProps.put("cache.secretKeys.size", -1l);
cacheProps.put("cache.secretKeys.maxLifetime", -1l);
cacheProps.put("cache.validatedDomains.size", -1l);
cacheProps.put("cache.validatedDomains.maxLifetime", -1l);
cacheProps.put("cache.directedPresences.size", -1l);
cacheProps.put("cache.directedPresences.maxLifetime", -1l);
cacheProps.put("cache.serverFeatures.size", -1l);
cacheProps.put("cache.serverFeatures.maxLifetime", -1l);
cacheProps.put("cache.serverItems.size", -1l);
cacheProps.put("cache.serverItems.maxLifetime", -1l);
cacheProps.put("cache.serversConfigurations.size", 128 * 1024l);
cacheProps.put("cache.serversConfigurations.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.entityCapabilities.size", -1l);
cacheProps.put("cache.entityCapabilities.maxLifetime", JiveConstants.DAY * 2);
cacheProps.put("cache.entityCapabilitiesUsers.size", -1l);
cacheProps.put("cache.entityCapabilitiesUsers.maxLifetime", JiveConstants.DAY * 2);
cacheProps.put("cache.entityCapabilitiesPendingHashes.size", -1l);
cacheProps.put("cache.entityCapabilitiesPendingHashes.maxLifetime", JiveConstants.DAY * 2);
cacheProps.put("cache.pluginCacheInfo.size", -1l);
cacheProps.put("cache.pluginCacheInfo.maxLifetime", -1l);
} }
private CacheFactory() { private CacheFactory() {
} }
/**
* If a local property is found for the supplied name which specifies a value for cache size, it is returned.
* Otherwise, the defaultSize argument is returned.
*
* @param cacheName the name of the cache to look up a corresponding property for.
* @return either the property value or the default value.
*/
public static long getMaxCacheSize(String cacheName) {
return getCacheProperty(cacheName, ".size", DEFAULT_MAX_CACHE_SIZE);
}
/**
* Sets a local property which overrides the maximum cache size as configured in coherence-cache-config.xml for the
* supplied cache name.
* @param cacheName the name of the cache to store a value for.
* @param size the maximum cache size.
*/
public static void setMaxSizeProperty(String cacheName, long size) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty("cache." + cacheName + ".size", Long.toString(size));
}
public static boolean hasMaxSizeFromProperty(String cacheName) {
return hasCacheProperty(cacheName, ".size");
}
/**
* If a local property is found for the supplied name which specifies a value for cache entry lifetime, it
* is returned. Otherwise, the defaultLifetime argument is returned.
*
* @param cacheName the name of the cache to look up a corresponding property for.
* @return either the property value or the default value.
*/
public static long getMaxCacheLifetime(String cacheName) {
return getCacheProperty(cacheName, ".maxLifetime", DEFAULT_MAX_CACHE_LIFETIME);
}
/**
* Sets a local property which overrides the maximum cache entry lifetime as configured in coherence-cache-config.xml
* for the supplied cache name.
* @param cacheName the name of the cache to store a value for.
* @param lifetime the maximum cache entry lifetime.
*/
public static void setMaxLifetimeProperty(String cacheName, long lifetime) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty(("cache." + cacheName + ".maxLifetime"), Long.toString(lifetime));
}
public static boolean hasMaxLifetimeFromProperty(String cacheName) {
return hasCacheProperty(cacheName, ".maxLifetime");
}
public static void setCacheTypeProperty(String cacheName, String type) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty("cache." + cacheName + ".type", type);
}
public static String getCacheTypeProperty(String cacheName) {
cacheName = cacheName.replaceAll(" ", "");
return JiveGlobals.getProperty("cache." + cacheName + ".type");
}
public static void setMinCacheSize(String cacheName, long size) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty("cache." + cacheName + ".min", Long.toString(size));
}
public static long getMinCacheSize(String cacheName) {
return getCacheProperty(cacheName, ".min", 0);
}
private static long getCacheProperty(String cacheName, String suffix, long defaultValue) {
// First check if user is overwriting default value using a system property for the cache name
String propName = "cache." + cacheName.replaceAll(" ", "") + suffix;
String sizeProp = JiveGlobals.getProperty(propName);
if (sizeProp == null && cacheNames.containsKey(cacheName)) {
// No system property was found for the cache name so try now with short name
propName = "cache." + cacheNames.get(cacheName) + suffix;
sizeProp = JiveGlobals.getProperty(propName);
}
if (sizeProp != null) {
try {
return Long.parseLong(sizeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse " + propName + " using default value.");
}
}
// Check if there is a default size value for this cache
Long defaultSize = cacheProps.get(propName);
return defaultSize == null ? defaultValue : defaultSize;
}
private static boolean hasCacheProperty(String cacheName, String suffix) {
// First check if user is overwriting default value using a system property for the cache name
String propName = "cache." + cacheName.replaceAll(" ", "") + suffix;
String sizeProp = JiveGlobals.getProperty(propName);
if (sizeProp == null && cacheNames.containsKey(cacheName)) {
// No system property was found for the cache name so try now with short name
propName = "cache." + cacheNames.get(cacheName) + suffix;
sizeProp = JiveGlobals.getProperty(propName);
}
if (sizeProp != null) {
try {
Long.parseLong(sizeProp);
return true;
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse " + propName + " using default value.");
}
}
return false;
}
/** /**
* Returns an array of all caches in the system. * Returns an array of all caches in the system.
* @return an array of all caches in the system. * @return an array of all caches in the system.
...@@ -74,7 +304,6 @@ public class CacheFactory { ...@@ -74,7 +304,6 @@ public class CacheFactory {
return values.toArray(new Cache[values.size()]); return values.toArray(new Cache[values.size()]);
} }
/** /**
* Returns the named cache, creating it as necessary. * Returns the named cache, creating it as necessary.
* *
......
...@@ -484,7 +484,7 @@ public class DefaultCache<K, V> implements Cache<K, V> { ...@@ -484,7 +484,7 @@ public class DefaultCache<K, V> implements Cache<K, V> {
*/ */
public void setMaxCacheSize(int maxCacheSize) { public void setMaxCacheSize(int maxCacheSize) {
this.maxCacheSize = maxCacheSize; this.maxCacheSize = maxCacheSize;
DefaultLocalCacheStrategy.setMaxSizeProperty(name, maxCacheSize); CacheFactory.setMaxSizeProperty(name, maxCacheSize);
// It's possible that the new max size is smaller than our current cache // It's possible that the new max size is smaller than our current cache
// size. If so, we need to delete infrequently used items. // size. If so, we need to delete infrequently used items.
cullCache(); cullCache();
...@@ -512,7 +512,7 @@ public class DefaultCache<K, V> implements Cache<K, V> { ...@@ -512,7 +512,7 @@ public class DefaultCache<K, V> implements Cache<K, V> {
*/ */
public void setMaxLifetime(long maxLifetime) { public void setMaxLifetime(long maxLifetime) {
this.maxLifetime = maxLifetime; this.maxLifetime = maxLifetime;
DefaultLocalCacheStrategy.setMaxLifetimeProperty(name, maxLifetime); CacheFactory.setMaxLifetimeProperty(name, maxLifetime);
} }
/** /**
......
...@@ -12,15 +12,9 @@ ...@@ -12,15 +12,9 @@
package org.jivesoftware.util.cache; package org.jivesoftware.util.cache;
import org.jivesoftware.openfire.cluster.ClusterNodeInfo; import org.jivesoftware.openfire.cluster.ClusterNodeInfo;
import org.jivesoftware.openfire.container.CacheInfo;
import org.jivesoftware.openfire.container.PluginCacheRegistry;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
...@@ -32,127 +26,8 @@ import java.util.Map; ...@@ -32,127 +26,8 @@ import java.util.Map;
*/ */
public class DefaultLocalCacheStrategy implements CacheFactoryStrategy { public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
public static final int DEFAULT_MAX_CACHE_SIZE = 1024 * 256;
public static final long DEFAULT_MAX_CACHE_LIFETIME = 6 * JiveConstants.HOUR;
/**
* This map contains property names which were used to store cache configuration data
* in local xml properties in previous versions.
*/
private static final Map<String, String> cacheNames = new HashMap<String, String>();
/**
* Default properties to use for local caches. Default properties can be overridden
* by setting the corresponding system properties.
*/
private static final Map<String, Long> cacheProps = new HashMap<String, Long>();
public DefaultLocalCacheStrategy() { public DefaultLocalCacheStrategy() {
initCacheNameMap();
}
private void initCacheNameMap() {
cacheNames.put("Favicon Hits", "faviconHits");
cacheNames.put("Favicon Misses", "faviconMisses");
cacheNames.put("Group", "group");
cacheNames.put("Group Metadata Cache", "groupMeta");
cacheNames.put("Javascript Cache", "javascript");
cacheNames.put("Last Activity Cache", "lastActivity");
cacheNames.put("Multicast Service", "multicast");
cacheNames.put("Offline Message Size", "offlinemessage");
cacheNames.put("Offline Presence Cache", "offlinePresence");
cacheNames.put("Privacy Lists", "listsCache");
cacheNames.put("Remote Users Existence", "remoteUsersCache");
cacheNames.put("Roster", "username2roster");
cacheNames.put("User", "userCache");
cacheNames.put("VCard", "vcardCache");
cacheNames.put("File Transfer Cache", "fileTransfer");
cacheNames.put("File Transfer", "transferProxy");
cacheNames.put("POP3 Authentication", "pop3");
cacheNames.put("LDAP Authentication", "ldap");
cacheNames.put("Routing Servers Cache", "routeServer");
cacheNames.put("Routing Components Cache", "routeComponent");
cacheNames.put("Routing Users Cache", "routeUser");
cacheNames.put("Routing AnonymousUsers Cache", "routeAnonymousUser");
cacheNames.put("Routing User Sessions", "routeUserSessions");
cacheNames.put("Components Sessions", "componentsSessions");
cacheNames.put("Connection Managers Sessions", "connManagerSessions");
cacheNames.put("Incoming Server Sessions", "incServerSessions");
cacheNames.put("Sessions by Hostname", "sessionsHostname");
cacheNames.put("Secret Keys Cache", "secretKeys");
cacheNames.put("Validated Domains", "validatedDomains");
cacheNames.put("Directed Presences", "directedPresences");
cacheNames.put("Disco Server Features", "serverFeatures");
cacheNames.put("Disco Server Items", "serverItems");
cacheNames.put("Remote Server Configurations", "serversConfigurations");
cacheNames.put("Entity Capabilities", "entityCapabilities");
cacheNames.put("Entity Capabilities Users", "entityCapabilitiesUsers");
cacheNames.put("Entity Capabilities Pending Hashes", "entityCapabilitiesPendingHashes");
cacheProps.put("cache.fileTransfer.size", 128 * 1024l);
cacheProps.put("cache.fileTransfer.maxLifetime", 1000 * 60 * 10l);
cacheProps.put("cache.multicast.size", 128 * 1024l);
cacheProps.put("cache.multicast.maxLifetime", JiveConstants.DAY);
cacheProps.put("cache.offlinemessage.size", 100 * 1024l);
cacheProps.put("cache.offlinemessage.maxLifetime", JiveConstants.HOUR * 12);
cacheProps.put("cache.pop3.size", 512 * 1024l);
cacheProps.put("cache.pop3.maxLifetime", JiveConstants.HOUR);
cacheProps.put("cache.transferProxy.size", -1l);
cacheProps.put("cache.transferProxy.maxLifetime", 1000 * 60 * 10l);
cacheProps.put("cache.group.size", 1024 * 1024l);
cacheProps.put("cache.group.maxLifetime", JiveConstants.MINUTE * 15);
cacheProps.put("cache.groupMeta.size", 512 * 1024l);
cacheProps.put("cache.groupMeta.maxLifetime", JiveConstants.MINUTE * 15);
cacheProps.put("cache.javascript.size", 128 * 1024l);
cacheProps.put("cache.javascript.maxLifetime", 3600 * 24 * 10l);
cacheProps.put("cache.ldap.size", 512 * 1024l);
cacheProps.put("cache.ldap.maxLifetime", JiveConstants.HOUR * 2);
cacheProps.put("cache.listsCache.size", 512 * 1024l);
cacheProps.put("cache.offlinePresence.size", 512 * 1024l);
cacheProps.put("cache.lastActivity.size", 128 * 1024l);
cacheProps.put("cache.userCache.size", 512 * 1024l);
cacheProps.put("cache.userCache.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.remoteUsersCache.size", 512 * 1024l);
cacheProps.put("cache.remoteUsersCache.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.vcardCache.size", 512 * 1024l);
cacheProps.put("cache.faviconHits.size", 128 * 1024l);
cacheProps.put("cache.faviconMisses.size", 128 * 1024l);
cacheProps.put("cache.routeServer.size", -1l);
cacheProps.put("cache.routeServer.maxLifetime", -1l);
cacheProps.put("cache.routeComponent.size", -1l);
cacheProps.put("cache.routeComponent.maxLifetime", -1l);
cacheProps.put("cache.routeUser.size", -1l);
cacheProps.put("cache.routeUser.maxLifetime", -1l);
cacheProps.put("cache.routeAnonymousUser.size", -1l);
cacheProps.put("cache.routeAnonymousUser.maxLifetime", -1l);
cacheProps.put("cache.routeUserSessions.size", -1l);
cacheProps.put("cache.routeUserSessions.maxLifetime", -1l);
cacheProps.put("cache.componentsSessions.size", -1l);
cacheProps.put("cache.componentsSessions.maxLifetime", -1l);
cacheProps.put("cache.connManagerSessions.size", -1l);
cacheProps.put("cache.connManagerSessions.maxLifetime", -1l);
cacheProps.put("cache.incServerSessions.size", -1l);
cacheProps.put("cache.incServerSessions.maxLifetime", -1l);
cacheProps.put("cache.sessionsHostname.size", -1l);
cacheProps.put("cache.sessionsHostname.maxLifetime", -1l);
cacheProps.put("cache.secretKeys.size", -1l);
cacheProps.put("cache.secretKeys.maxLifetime", -1l);
cacheProps.put("cache.validatedDomains.size", -1l);
cacheProps.put("cache.validatedDomains.maxLifetime", -1l);
cacheProps.put("cache.directedPresences.size", -1l);
cacheProps.put("cache.directedPresences.maxLifetime", -1l);
cacheProps.put("cache.serverFeatures.size", -1l);
cacheProps.put("cache.serverFeatures.maxLifetime", -1l);
cacheProps.put("cache.serverItems.size", -1l);
cacheProps.put("cache.serverItems.maxLifetime", -1l);
cacheProps.put("cache.serversConfigurations.size", 128 * 1024l);
cacheProps.put("cache.serversConfigurations.maxLifetime", JiveConstants.MINUTE * 30);
cacheProps.put("cache.entityCapabilities.size", -1l);
cacheProps.put("cache.entityCapabilities.maxLifetime", JiveConstants.DAY * 2);
cacheProps.put("cache.entityCapabilitiesUsers.size", -1l);
cacheProps.put("cache.entityCapabilitiesUsers.maxLifetime", JiveConstants.DAY * 2);
cacheProps.put("cache.entityCapabilitiesPendingHashes.size", -1l);
cacheProps.put("cache.entityCapabilitiesPendingHashes.maxLifetime", JiveConstants.DAY * 2);
} }
public boolean startCluster() { public boolean startCluster() {
...@@ -163,16 +38,11 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy { ...@@ -163,16 +38,11 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
} }
public Cache createCache(String name) { public Cache createCache(String name) {
String propname = cacheNames.get(name); // Get cache configuration from system properties or default (hardcoded) values
if (propname == null) { long maxSize = CacheFactory.getMaxCacheSize(name);
propname = name; long lifetime = CacheFactory.getMaxCacheLifetime(name);
}
// Check if there is a cache configuration. If not check for system properties to configure cache
CacheInfo cacheInfo = PluginCacheRegistry.getCacheInfo(name);
long maxSizeFromProperty = cacheInfo != null ? getMaxSizeFromProperty(cacheInfo) : getMaxSizeFromProperty(propname);
long lifetimeFromProperty = cacheInfo != null ? getMaxLifetimeFromProperty(cacheInfo) : getMaxLifetimeFromProperty(propname);
// Create cache with located properties // Create cache with located properties
return new DefaultCache(name, maxSizeFromProperty, lifetimeFromProperty); return new DefaultCache(name, maxSize, lifetime);
} }
public void destroyCache(Cache cache) { public void destroyCache(Cache cache) {
...@@ -222,116 +92,4 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy { ...@@ -222,116 +92,4 @@ public class DefaultLocalCacheStrategy implements CacheFactoryStrategy {
public void unlockKey(Object key) { public void unlockKey(Object key) {
} }
/**
* Sets a local property which overrides the maximum cache size as configured in coherence-cache-config.xml for the
* supplied cache name.
* @param cacheName the name of the cache to store a value for.
* @param size the maximum cache size.
*/
public static void setMaxSizeProperty(String cacheName, int size) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty("cache." + cacheName + ".size", Integer.toString(size));
}
/**
* Sets a local property which overrides the maximum cache entry lifetime as configured in coherence-cache-config.xml
* for the supplied cache name.
* @param cacheName the name of the cache to store a value for.
* @param lifetime the maximum cache entry lifetime.
*/
public static void setMaxLifetimeProperty(String cacheName, long lifetime) {
cacheName = cacheName.replaceAll(" ", "");
JiveGlobals.setProperty(("cache." + cacheName + ".maxLifetime"), Long.toString(lifetime));
}
/**
* If a local property is found for the supplied name which specifies a value for cache size, it is returned.
* Otherwise, the defaultSize argument is returned.
*
* @param cacheName the name of the cache to look up a corresponding property for.
* @return either the property value or the default value.
*/
private static long getMaxSizeFromProperty(String cacheName) {
String propName = "cache." + cacheName.replaceAll(" ", "") + ".size";
String sizeProp = JiveGlobals.getProperty(propName);
if (sizeProp != null) {
try {
return Integer.parseInt(sizeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse " + propName + " using default value.");
}
}
// Check if there is a default size value for this cache
Long defaultSize = cacheProps.get(propName);
return defaultSize == null ? DEFAULT_MAX_CACHE_SIZE : defaultSize;
}
private static long getMaxSizeFromProperty(CacheInfo cacheInfo) {
String sizeProp = cacheInfo.getParams().get("back-size-high");
if (sizeProp != null) {
if ("0".equals(sizeProp)) {
return -1l;
}
try {
return Integer.parseInt(sizeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse back-size-high for cache: " + cacheInfo.getCacheName());
}
}
// Return default
return DEFAULT_MAX_CACHE_SIZE;
}
/**
* If a local property is found for the supplied name which specifies a value for cache entry lifetime, it
* is returned. Otherwise, the defaultLifetime argument is returned.
*
* @param cacheName the name of the cache to look up a corresponding property for.
* @return either the property value or the default value.
*/
private static long getMaxLifetimeFromProperty(String cacheName) {
String propName = "cache." + cacheName.replaceAll(" ", "") + ".maxLifetime";
String lifetimeProp = JiveGlobals.getProperty(propName);
if (lifetimeProp != null) {
try {
return Long.parseLong(lifetimeProp);
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse " + propName + " using default value.");
}
}
// Check if there is a default lifetime value for this cache
Long defaultLifetime = cacheProps.get(propName);
return defaultLifetime == null ? DEFAULT_MAX_CACHE_LIFETIME : defaultLifetime;
}
private static long getMaxLifetimeFromProperty(CacheInfo cacheInfo) {
String lifetimeProp = cacheInfo.getParams().get("back-size-high");
if (lifetimeProp != null) {
if ("0".equals(lifetimeProp)) {
return -1l;
}
long factor = 1;
if (lifetimeProp.endsWith("m")) {
factor = JiveConstants.MINUTE;
}
else if (lifetimeProp.endsWith("h")) {
factor = JiveConstants.HOUR;
}
else if (lifetimeProp.endsWith("d")) {
factor = JiveConstants.DAY;
}
try {
return Long.parseLong(lifetimeProp.substring(0, lifetimeProp.length()-1)) * factor;
}
catch (NumberFormatException nfe) {
Log.warn("Unable to parse back-size-high for cache: " + cacheInfo.getCacheName());
}
}
// Return default
return DEFAULT_MAX_CACHE_LIFETIME;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment