From 3fc215d04129361fb172b51ddf656bcd9efd30d6 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Tue, 5 Jul 2016 19:54:55 +0200 Subject: [PATCH] KEYCLOAK-3202 Creating users causes memory leak --- .../demo-dist/src/main/xslt/standalone.xsl | 3 -- .../cli/keycloak-install-ha.cli | 2 -- ...ltInfinispanConnectionProviderFactory.java | 36 +++++++++++++++++-- .../InfinispanConnectionProvider.java | 20 +++++++---- .../models/cache/infinispan/CacheManager.java | 1 + .../InfinispanCacheRealmProviderFactory.java | 2 +- .../InfinispanCacheUserProviderFactory.java | 2 +- .../cache/infinispan/UserCacheManager.java | 1 + .../KeycloakServerDeploymentProcessor.java | 1 - .../keycloak-infinispan.xml | 6 ---- 10 files changed, 51 insertions(+), 23 deletions(-) diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl index 94dd49c554..4a18a1db53 100755 --- a/distribution/demo-dist/src/main/xslt/standalone.xsl +++ b/distribution/demo-dist/src/main/xslt/standalone.xsl @@ -90,9 +90,6 @@ - - - diff --git a/distribution/server-overlay/cli/keycloak-install-ha.cli b/distribution/server-overlay/cli/keycloak-install-ha.cli index e0ad848848..4b8d399e36 100644 --- a/distribution/server-overlay/cli/keycloak-install-ha.cli +++ b/distribution/server-overlay/cli/keycloak-install-ha.cli @@ -8,7 +8,5 @@ embed-server --server-config=standalone-ha.xml /subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:add(mode="SYNC",owners="1") /subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:add(mode="SYNC",owners="1") /subsystem=infinispan/cache-container=keycloak/replicated-cache=work:add(mode="SYNC") -/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions:add() -/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/transaction=TRANSACTION:add(mode=BATCH,locking=PESSIMISTIC) /extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem) /subsystem=keycloak-server:add(web-context=auth) \ No newline at end of file diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java index c9311bd752..3bad384976 100755 --- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java @@ -21,6 +21,7 @@ import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfigurationBuilder; +import org.infinispan.eviction.EvictionStrategy; import org.infinispan.eviction.EvictionType; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; @@ -97,6 +98,17 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon cacheManager = (EmbeddedCacheManager) new InitialContext().lookup(cacheContainerLookup); containerManaged = true; + cacheManager.defineConfiguration(InfinispanConnectionProvider.REALM_REVISIONS_CACHE_NAME, getRevisionCacheConfig(true, InfinispanConnectionProvider.REALM_REVISIONS_CACHE_DEFAULT_MAX)); + cacheManager.getCache(InfinispanConnectionProvider.REALM_CACHE_NAME, true); + + long maxEntries = cacheManager.getCache(InfinispanConnectionProvider.USER_CACHE_NAME).getCacheConfiguration().eviction().maxEntries(); + if (maxEntries <= 0) { + maxEntries = InfinispanConnectionProvider.USER_REVISIONS_CACHE_DEFAULT_MAX; + } + + cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, getRevisionCacheConfig(true, maxEntries)); + cacheManager.getCache(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, true); + logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup); } catch (Exception e) { throw new RuntimeException("Failed to retrieve cache container", e); @@ -162,12 +174,32 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon .transaction().transactionMode(TransactionMode.TRANSACTIONAL); counterConfigBuilder.transaction().transactionManagerLookup(new DummyTransactionManagerLookup()); counterConfigBuilder.transaction().lockingMode(LockingMode.PESSIMISTIC); - Configuration counterCacheConfiguration = counterConfigBuilder.build(); - cacheManager.defineConfiguration(InfinispanConnectionProvider.VERSION_CACHE_NAME, counterCacheConfiguration); + cacheManager.defineConfiguration(InfinispanConnectionProvider.REALM_REVISIONS_CACHE_NAME, getRevisionCacheConfig(false, InfinispanConnectionProvider.REALM_REVISIONS_CACHE_DEFAULT_MAX)); + cacheManager.getCache(InfinispanConnectionProvider.REALM_CACHE_NAME, true); cacheManager.defineConfiguration(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME, new ConfigurationBuilder().eviction().type(EvictionType.COUNT).size(100).simpleCache(true).build()); + + long maxEntries = cacheManager.getCache(InfinispanConnectionProvider.USER_CACHE_NAME).getCacheConfiguration().eviction().maxEntries(); + if (maxEntries <= 0) { + maxEntries = InfinispanConnectionProvider.USER_REVISIONS_CACHE_DEFAULT_MAX; + } + + cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, getRevisionCacheConfig(false, maxEntries)); + cacheManager.getCache(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, true); + } + + private Configuration getRevisionCacheConfig(boolean managed, long maxEntries) { + ConfigurationBuilder cb = new ConfigurationBuilder(); + cb.invocationBatching().enable().transaction().transactionMode(TransactionMode.TRANSACTIONAL); + if (!managed) { + cb.transaction().transactionManagerLookup(new DummyTransactionManagerLookup()); + } + cb.transaction().lockingMode(LockingMode.PESSIMISTIC); + + cb.eviction().strategy(EvictionStrategy.LRU).type(EvictionType.COUNT).size(maxEntries); + return cb.build(); } } diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/InfinispanConnectionProvider.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/InfinispanConnectionProvider.java index 0fc2bc0b5e..143056ca9a 100755 --- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/InfinispanConnectionProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/InfinispanConnectionProvider.java @@ -25,15 +25,21 @@ import org.keycloak.provider.Provider; */ public interface InfinispanConnectionProvider extends Provider { - public static final String VERSION_CACHE_NAME = "realmVersions"; - static final String REALM_CACHE_NAME = "realms"; - static final String USER_CACHE_NAME = "users"; - static final String SESSION_CACHE_NAME = "sessions"; - static final String OFFLINE_SESSION_CACHE_NAME = "offlineSessions"; - static final String LOGIN_FAILURE_CACHE_NAME = "loginFailures"; - static final String WORK_CACHE_NAME = "work"; + String REALM_CACHE_NAME = "realms"; + String REALM_REVISIONS_CACHE_NAME = "realmRevisions"; + int REALM_REVISIONS_CACHE_DEFAULT_MAX = 10000; + + String USER_CACHE_NAME = "users"; + String USER_REVISIONS_CACHE_NAME = "userRevisions"; + int USER_REVISIONS_CACHE_DEFAULT_MAX = 100000; + + String SESSION_CACHE_NAME = "sessions"; + String OFFLINE_SESSION_CACHE_NAME = "offlineSessions"; + String LOGIN_FAILURE_CACHE_NAME = "loginFailures"; + String WORK_CACHE_NAME = "work"; String AUTHORIZATION_CACHE_NAME = "authorization"; + Cache getCache(String name); } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/CacheManager.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/CacheManager.java index e41913d4f6..bf2b1c27e1 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/CacheManager.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/CacheManager.java @@ -139,6 +139,7 @@ public abstract class CacheManager { public void clear() { cache.clear(); + revisions.clear(); } public void addInvalidations(Predicate> predicate, Set invalidations) { diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java index f32ac69369..40c4e0928b 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheRealmProviderFactory.java @@ -48,7 +48,7 @@ public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFa synchronized (this) { if (realmCache == null) { Cache cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME); - Cache revisions = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.VERSION_CACHE_NAME); + Cache revisions = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_REVISIONS_CACHE_NAME); realmCache = new RealmCacheManager(cache, revisions); } } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java index 9e93d55141..e0409b1aa5 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java @@ -55,7 +55,7 @@ public class InfinispanCacheUserProviderFactory implements CacheUserProviderFact synchronized (this) { if (userCache == null) { Cache cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.USER_CACHE_NAME); - Cache revisions = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.VERSION_CACHE_NAME); + Cache revisions = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME); userCache = new UserCacheManager(cache, revisions); } } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheManager.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheManager.java index e1fb79cbdc..d3564d0368 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheManager.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheManager.java @@ -45,6 +45,7 @@ public class UserCacheManager extends CacheManager { @Override public void clear() { cache.clear(); + revisions.clear(); } @Override diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java index 8b4840a324..20b54ea39b 100755 --- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java +++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java @@ -63,7 +63,6 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso st.addDependency(cacheContainerService.append("offlineSessions")); st.addDependency(cacheContainerService.append("loginFailures")); st.addDependency(cacheContainerService.append("work")); - st.addDependency(cacheContainerService.append("realmVersions")); } } diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml index 96d47809d5..35b42299fb 100755 --- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml +++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml @@ -33,9 +33,6 @@ - - - @@ -99,9 +96,6 @@ - - -