From 860a1048287509fd4fe8c42fd3269652d90109a5 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Fri, 12 Feb 2016 00:30:36 -0500 Subject: [PATCH] stress testing --- .../infinispan/DefaultCacheRealmProvider.java | 32 ++++---- .../InfinispanCacheRealmProviderFactory.java | 6 +- .../infinispan/InfinispanRealmCache.java | 47 +++++------- .../models/cache/infinispan/RealmAdapter.java | 20 +++-- .../locking/LockingCacheRealmProvider.java | 59 +++++++++++---- .../LockingCacheRealmProviderFactory.java | 16 ++-- .../infinispan/locking/LockingRealmCache.java | 74 ++++++++++--------- .../keycloak/models/jpa/JpaRealmProvider.java | 11 +++ .../org/keycloak/models/jpa/RealmAdapter.java | 2 +- .../models/jpa/entities/ClientEntity.java | 2 + .../keycloak/adapters/MongoRealmProvider.java | 11 +++ .../mongo/keycloak/adapters/RealmAdapter.java | 7 +- .../org/keycloak/models/RealmProvider.java | 5 +- .../org/keycloak/models/cache/RealmCache.java | 36 ++++----- .../models/cache/entities/CachedClient.java | 2 +- .../models/cache/entities/CachedRealm.java | 28 ++++++- .../keycloak/test/stress/MaxRateExecutor.java | 8 +- .../org/keycloak/test/LoginLogoutTest.java | 3 +- 18 files changed, 222 insertions(+), 147 deletions(-) diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java index d80b8175df..a177b95f0d 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java @@ -120,7 +120,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { protected void runInvalidations() { for (String id : realmInvalidations) { - cache.invalidateCachedRealmById(id); + cache.invalidateRealmById(id); } for (String id : roleInvalidations) { cache.invalidateRoleById(id); @@ -129,10 +129,10 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { cache.invalidateGroupById(id); } for (String id : appInvalidations) { - cache.invalidateCachedApplicationById(id); + cache.invalidateClientById(id); } for (String id : clientTemplateInvalidations) { - cache.invalidateCachedClientTemplateById(id); + cache.invalidateClientTemplateById(id); } } @@ -193,13 +193,13 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { @Override public RealmModel getRealm(String id) { - CachedRealm cached = cache.getCachedRealm(id); + CachedRealm cached = cache.getRealm(id); if (cached == null) { RealmModel model = getDelegate().getRealm(id); if (model == null) return null; if (realmInvalidations.contains(id)) return model; cached = new CachedRealm(cache, this, model); - cache.addCachedRealm(cached); + cache.addRealm(cached); } else if (realmInvalidations.contains(id)) { return getDelegate().getRealm(id); } else if (managedRealms.containsKey(id)) { @@ -212,13 +212,13 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { @Override public RealmModel getRealmByName(String name) { - CachedRealm cached = cache.getCachedRealmByName(name); + CachedRealm cached = cache.getRealmByName(name); if (cached == null) { RealmModel model = getDelegate().getRealmByName(name); if (model == null) return null; if (realmInvalidations.contains(model.getId())) return model; cached = new CachedRealm(cache, this, model); - cache.addCachedRealm(cached); + cache.addRealm(cached); } else if (realmInvalidations.contains(cached.getId())) { return getDelegate().getRealmByName(name); } else if (managedRealms.containsKey(cached.getId())) { @@ -245,7 +245,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { @Override public boolean removeRealm(String id) { - cache.invalidateCachedRealmById(id); + cache.invalidateRealmById(id); RealmModel realm = getDelegate().getRealm(id); Set realmRoles = null; @@ -287,7 +287,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { } else { cached = new CachedRealmRole(model, realm); } - cache.addCachedRole(cached); + cache.addRole(cached); } else if (roleInvalidations.contains(id)) { return getDelegate().getRoleById(id, realm); @@ -311,7 +311,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (groupInvalidations.contains(id)) return model; cached = new CachedGroup(realm, model); - cache.addCachedGroup(cached); + cache.addGroup(cached); } else if (groupInvalidations.contains(id)) { return getDelegate().getGroupById(id, realm); @@ -325,7 +325,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { @Override public ClientModel getClientById(String id, RealmModel realm) { - CachedClient cached = cache.getApplication(id); + CachedClient cached = cache.getClient(id); if (cached != null && !cached.getRealm().equals(realm.getId())) { cached = null; } @@ -335,7 +335,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (appInvalidations.contains(id)) return model; cached = new CachedClient(cache, getDelegate(), realm, model); - cache.addCachedClient(cached); + cache.addClient(cached); } else if (appInvalidations.contains(id)) { return getDelegate().getClientById(id, realm); } else if (managedApplications.containsKey(id)) { @@ -345,6 +345,12 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { managedApplications.put(id, adapter); return adapter; } + + @Override + public ClientModel getClientByClientId(String clientId, RealmModel realm) { + return getDelegate().getClientByClientId(clientId, realm); + } + @Override public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) { CachedClientTemplate cached = cache.getClientTemplate(id); @@ -357,7 +363,7 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (clientTemplateInvalidations.contains(id)) return model; cached = new CachedClientTemplate(cache, getDelegate(), realm, model); - cache.addCachedClientTemplate(cached); + cache.addClientTemplate(cached); } else if (clientTemplateInvalidations.contains(id)) { return getDelegate().getClientTemplateById(id, realm); } else if (managedClientTemplates.containsKey(id)) { 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 3c6573341b..ac8f3734fd 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 @@ -138,11 +138,11 @@ public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFa realmLookup.remove(realm.getName()); for (String r : realm.getRealmRoles().values()) { - realmCache.evictCachedRoleById(r); + realmCache.evictRoleById(r); } for (String c : realm.getClients().values()) { - realmCache.evictCachedApplicationById(c); + realmCache.evictClientById(c); } log.tracev("Realm removed realm={0}", realm.getName()); @@ -150,7 +150,7 @@ public class InfinispanCacheRealmProviderFactory implements CacheRealmProviderFa CachedClient client = (CachedClient) object; for (String r : client.getRoles().values()) { - realmCache.evictCachedRoleById(r); + realmCache.evictRoleById(r); } log.tracev("Client removed client={0}", client.getId()); diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java index 4f89237922..8dfe923c28 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java @@ -53,61 +53,61 @@ public class InfinispanRealmCache implements RealmCache { } @Override - public CachedRealm getCachedRealm(String id) { + public CachedRealm getRealm(String id) { return get(id, CachedRealm.class); } @Override - public void invalidateCachedRealm(CachedRealm realm) { + public void invalidateRealm(CachedRealm realm) { logger.tracev("Invalidating realm {0}", realm.getId()); cache.remove(realm.getId()); realmLookup.remove(realm.getName()); } @Override - public void invalidateCachedRealmById(String id) { + public void invalidateRealmById(String id) { CachedRealm cached = (CachedRealm) cache.remove(id); if (cached != null) realmLookup.remove(cached.getName()); } @Override - public void addCachedRealm(CachedRealm realm) { + public void addRealm(CachedRealm realm) { logger.tracev("Adding realm {0}", realm.getId()); cache.putForExternalRead(realm.getId(), realm); realmLookup.put(realm.getName(), realm.getId()); } @Override - public CachedRealm getCachedRealmByName(String name) { + public CachedRealm getRealmByName(String name) { String id = realmLookup.get(name); - return id != null ? getCachedRealm(id) : null; + return id != null ? getRealm(id) : null; } @Override - public CachedClient getApplication(String id) { + public CachedClient getClient(String id) { return get(id, CachedClient.class); } @Override - public void invalidateApplication(CachedClient app) { + public void invalidateClient(CachedClient app) { logger.tracev("Removing application {0}", app.getId()); cache.remove(app.getId()); } @Override - public void addCachedClient(CachedClient app) { + public void addClient(CachedClient app) { logger.tracev("Adding application {0}", app.getId()); cache.putForExternalRead(app.getId(), app); } @Override - public void invalidateCachedApplicationById(String id) { + public void invalidateClientById(String id) { logger.tracev("Removing application {0}", id); cache.remove(id); } @Override - public void evictCachedApplicationById(String id) { + public void evictClientById(String id) { logger.tracev("Evicting application {0}", id); cache.evict(id); } @@ -124,18 +124,11 @@ public class InfinispanRealmCache implements RealmCache { } @Override - public void addCachedGroup(CachedGroup role) { + public void addGroup(CachedGroup role) { logger.tracev("Adding group {0}", role.getId()); cache.putForExternalRead(role.getId(), role); } - @Override - public void invalidateCachedGroupById(String id) { - logger.tracev("Removing group {0}", id); - cache.remove(id); - - } - @Override public void invalidateGroupById(String id) { logger.tracev("Removing group {0}", id); @@ -160,23 +153,17 @@ public class InfinispanRealmCache implements RealmCache { } @Override - public void evictCachedRoleById(String id) { + public void evictRoleById(String id) { logger.tracev("Evicting role {0}", id); cache.evict(id); } @Override - public void addCachedRole(CachedRole role) { + public void addRole(CachedRole role) { logger.tracev("Adding role {0}", role.getId()); cache.putForExternalRead(role.getId(), role); } - @Override - public void invalidateCachedRoleById(String id) { - logger.tracev("Removing role {0}", id); - cache.remove(id); - } - private T get(String id, Class type) { Object o = cache.get(id); return o != null && type.isInstance(o) ? type.cast(o) : null; @@ -194,19 +181,19 @@ public class InfinispanRealmCache implements RealmCache { } @Override - public void addCachedClientTemplate(CachedClientTemplate app) { + public void addClientTemplate(CachedClientTemplate app) { logger.tracev("Adding client template {0}", app.getId()); cache.putForExternalRead(app.getId(), app); } @Override - public void invalidateCachedClientTemplateById(String id) { + public void invalidateClientTemplateById(String id) { logger.tracev("Removing client template {0}", id); cache.remove(id); } @Override - public void evictCachedClientTemplateById(String id) { + public void evictClientTemplateById(String id) { logger.tracev("Evicting client template {0}", id); cache.evict(id); } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java index 41dc8d830a..14e2850752 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java @@ -415,6 +415,9 @@ public class RealmAdapter implements RealmModel { @Override public PublicKey getPublicKey() { + if (updated != null) return updated.getPublicKey(); + if (publicKey != null) return publicKey; + publicKey = cached.getPublicKey(); if (publicKey != null) return publicKey; publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem()); return publicKey; @@ -429,6 +432,9 @@ public class RealmAdapter implements RealmModel { @Override public X509Certificate getCertificate() { + if (updated != null) return updated.getCertificate(); + if (certificate != null) return certificate; + certificate = cached.getCertificate(); if (certificate != null) return certificate; certificate = KeycloakModelUtils.getCertificate(getCertificatePem()); return certificate; @@ -456,7 +462,14 @@ public class RealmAdapter implements RealmModel { @Override public PrivateKey getPrivateKey() { - if (privateKey != null) return privateKey; + if (updated != null) return updated.getPrivateKey(); + if (privateKey != null) { + return privateKey; + } + privateKey = cached.getPrivateKey(); + if (privateKey != null) { + return privateKey; + } privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem()); return privateKey; } @@ -635,10 +648,7 @@ public class RealmAdapter implements RealmModel { @Override public ClientModel getClientByClientId(String clientId) { - if (updated != null) return updated.getClientByClientId(clientId); - String id = cached.getClients().get(clientId); - if (id == null) return null; - return getClientById(id); + return cacheSession.getClientByClientId(clientId, this); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java index 162a36a737..a15f4f1f4b 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java @@ -132,7 +132,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { protected void runInvalidations() { for (String id : realmInvalidations) { - cache.invalidateCachedRealmById(id); + cache.invalidateRealmById(id); } for (String id : roleInvalidations) { cache.invalidateRoleById(id); @@ -141,10 +141,10 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { cache.invalidateGroupById(id); } for (String id : appInvalidations) { - cache.invalidateCachedApplicationById(id); + cache.invalidateClientById(id); } for (String id : clientTemplateInvalidations) { - cache.invalidateCachedClientTemplateById(id); + cache.invalidateClientTemplateById(id); } } @@ -271,7 +271,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { @Override public RealmModel getRealm(String id) { - CachedRealm cached = cache.getCachedRealm(id); + CachedRealm cached = cache.getRealm(id); if (cached != null) { logger.tracev("by id cache hit: {0}", cached.getName()); } @@ -282,7 +282,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (realmInvalidations.contains(id)) return model; cached = new RevisionedCachedRealm(loaded, cache, this, model); - cache.addCachedRealm(cached); + cache.addRealm(cached); } else if (realmInvalidations.contains(id)) { return getDelegate().getRealm(id); } else if (managedRealms.containsKey(id)) { @@ -295,7 +295,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { @Override public RealmModel getRealmByName(String name) { - CachedRealm cached = cache.getCachedRealmByName(name); + CachedRealm cached = cache.getRealmByName(name); if (cached != null) { logger.tracev("by name cache hit: {0}", cached.getName()); } @@ -305,7 +305,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (realmInvalidations.contains(model.getId())) return model; cached = new RevisionedCachedRealm(loaded, cache, this, model); - cache.addCachedRealm(cached); + cache.addRealm(cached); } else if (realmInvalidations.contains(cached.getId())) { return getDelegate().getRealmByName(name); } else if (managedRealms.containsKey(cached.getId())) { @@ -332,7 +332,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { @Override public boolean removeRealm(String id) { - cache.invalidateCachedRealmById(id); + cache.invalidateRealmById(id); RealmModel realm = getDelegate().getRealm(id); Set realmRoles = null; @@ -376,7 +376,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { } else { cached = new RevisionedCachedRealmRole(loaded, model, realm); } - cache.addCachedRole(cached); + cache.addRole(cached); } else if (roleInvalidations.contains(id)) { return getDelegate().getRoleById(id, realm); @@ -402,7 +402,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (groupInvalidations.contains(id)) return model; cached = new RevisionedCachedGroup(loaded, realm, model); - cache.addCachedGroup(cached); + cache.addGroup(cached); } else if (groupInvalidations.contains(id)) { return getDelegate().getGroupById(id, realm); @@ -416,11 +416,11 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { @Override public ClientModel getClientById(String id, RealmModel realm) { - CachedClient cached = cache.getApplication(id); + CachedClient cached = cache.getClient(id); if (cached != null && !cached.getRealm().equals(realm.getId())) { cached = null; } - if (cached != null && cached.getClientId().equals("client")) { + if (cached != null) { logger.tracev("client by id cache hit: {0}", cached.getClientId()); } @@ -431,7 +431,8 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (appInvalidations.contains(id)) return model; cached = new RevisionedCachedClient(loaded, cache, getDelegate(), realm, model); - cache.addCachedClient(cached); + logger.tracev("adding client by id cache miss: {0}", cached.getClientId()); + cache.addClient(cached); } else if (appInvalidations.contains(id)) { return getDelegate().getClientById(id, realm); } else if (managedApplications.containsKey(id)) { @@ -441,6 +442,36 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { managedApplications.put(id, adapter); return adapter; } + + @Override + public ClientModel getClientByClientId(String clientId, RealmModel realm) { + CachedClient cached = cache.getClientByClientId(clientId); + if (cached != null && !cached.getRealm().equals(realm.getId())) { + cached = null; + } + if (cached != null) { + logger.tracev("client by name cache hit: {0}", cached.getClientId()); + } + + if (cached == null) { + Long loaded = UpdateCounter.current(); + if (loaded == null) loaded = UpdateCounter.current(); + ClientModel model = getDelegate().getClientByClientId(clientId, realm); + if (model == null) return null; + if (appInvalidations.contains(model.getId())) return model; + cached = new RevisionedCachedClient(loaded, cache, getDelegate(), realm, model); + logger.tracev("adding client by name cache miss: {0}", cached.getClientId()); + cache.addClient(cached); + } else if (appInvalidations.contains(cached.getId())) { + return getDelegate().getClientById(cached.getId(), realm); + } else if (managedApplications.containsKey(cached.getId())) { + return managedApplications.get(cached.getId()); + } + ClientAdapter adapter = new ClientAdapter(realm, cached, this, cache); + managedApplications.put(cached.getId(), adapter); + return adapter; + } + @Override public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) { CachedClientTemplate cached = cache.getClientTemplate(id); @@ -455,7 +486,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider { if (model == null) return null; if (clientTemplateInvalidations.contains(id)) return model; cached = new RevisionedCachedClientTemplate(loaded, cache, getDelegate(), realm, model); - cache.addCachedClientTemplate(cached); + cache.addClientTemplate(cached); } else if (clientTemplateInvalidations.contains(id)) { return getDelegate().getClientTemplateById(id, realm); } else if (managedClientTemplates.containsKey(id)) { diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java index f143ea3ffd..67230484a1 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java @@ -37,8 +37,6 @@ import org.keycloak.models.cache.CacheRealmProviderFactory; import org.keycloak.models.cache.entities.CachedClient; import org.keycloak.models.cache.entities.CachedRealm; -import java.util.concurrent.ConcurrentHashMap; - /** * @author Bill Burke * @author Stian Thorgersen @@ -49,8 +47,6 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto protected volatile LockingRealmCache realmCache; - protected final ConcurrentHashMap realmLookup = new ConcurrentHashMap<>(); - @Override public CacheRealmProvider create(KeycloakSession session) { lazyInit(session); @@ -64,7 +60,7 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto Cache cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME); Cache counterCache = session.getProvider(InfinispanConnectionProvider.class).getCache(LockingConnectionProviderFactory.VERSION_CACHE_NAME); cache.addListener(new CacheListener()); - realmCache = new LockingRealmCache(cache, counterCache, realmLookup); + realmCache = new LockingRealmCache(cache, counterCache); } } } @@ -98,7 +94,7 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto if (object != null) { if (object instanceof CachedRealm) { CachedRealm realm = (CachedRealm) object; - realmLookup.put(realm.getName(), realm.getId()); + realmCache.getRealmLookup().put(realm.getName(), realm.getId()); log.tracev("Realm added realm={0}", realm.getName()); } } @@ -136,14 +132,14 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto if (object instanceof CachedRealm) { CachedRealm realm = (CachedRealm) object; - realmLookup.remove(realm.getName()); + realmCache.getRealmLookup().remove(realm.getName()); for (String r : realm.getRealmRoles().values()) { - realmCache.evictCachedRoleById(r); + realmCache.evictRoleById(r); } for (String c : realm.getClients().values()) { - realmCache.evictCachedApplicationById(c); + realmCache.evictClientById(c); } log.tracev("Realm removed realm={0}", realm.getName()); @@ -151,7 +147,7 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto CachedClient client = (CachedClient) object; for (String r : client.getRoles().values()) { - realmCache.evictCachedRoleById(r); + realmCache.evictRoleById(r); } log.tracev("Client removed client={0}", client.getId()); diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java index 2460502d91..5b3060d9c0 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java @@ -27,7 +27,6 @@ import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.cache.entities.CachedRole; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; /** * @author Stian Thorgersen @@ -39,11 +38,11 @@ public class LockingRealmCache implements RealmCache { protected final Cache revisions; protected final Cache cache; - protected final ConcurrentHashMap realmLookup; + protected final ConcurrentHashMap realmLookup = new ConcurrentHashMap<>(); + protected final ConcurrentHashMap clientLookup = new ConcurrentHashMap<>(); - public LockingRealmCache(Cache cache, Cache revisions, ConcurrentHashMap realmLookup) { + public LockingRealmCache(Cache cache, Cache revisions) { this.cache = cache; - this.realmLookup = realmLookup; this.revisions = revisions; } @@ -55,6 +54,14 @@ public class LockingRealmCache implements RealmCache { return revisions; } + public ConcurrentHashMap getRealmLookup() { + return realmLookup; + } + + public ConcurrentHashMap getClientLookup() { + return clientLookup; + } + public Long getCurrentRevision(String id) { return revisions.get(id); } @@ -133,25 +140,25 @@ public class LockingRealmCache implements RealmCache { } @Override - public CachedRealm getCachedRealm(String id) { + public CachedRealm getRealm(String id) { return get(id, CachedRealm.class); } @Override - public void invalidateCachedRealm(CachedRealm realm) { + public void invalidateRealm(CachedRealm realm) { logger.tracev("Invalidating realm {0}", realm.getId()); invalidateObject(realm.getId()); realmLookup.remove(realm.getName()); } @Override - public void invalidateCachedRealmById(String id) { + public void invalidateRealmById(String id) { CachedRealm cached = (CachedRealm) invalidateObject(id); if (cached != null) realmLookup.remove(cached.getName()); } @Override - public void addCachedRealm(CachedRealm realm) { + public void addRealm(CachedRealm realm) { logger.tracev("Adding realm {0}", realm.getId()); addRevisioned(realm.getId(), (Revisioned) realm); realmLookup.put(realm.getName(), realm.getId()); @@ -159,36 +166,46 @@ public class LockingRealmCache implements RealmCache { @Override - public CachedRealm getCachedRealmByName(String name) { + public CachedRealm getRealmByName(String name) { String id = realmLookup.get(name); - return id != null ? getCachedRealm(id) : null; + return id != null ? getRealm(id) : null; } @Override - public CachedClient getApplication(String id) { + public CachedClient getClient(String id) { return get(id, CachedClient.class); } + public CachedClient getClientByClientId(String clientId) { + String id = clientLookup.get(clientId); + return id != null ? getClient(id) : null; + } + @Override - public void invalidateApplication(CachedClient app) { + public void invalidateClient(CachedClient app) { logger.tracev("Removing application {0}", app.getId()); invalidateObject(app.getId()); + clientLookup.remove(app.getClientId()); } @Override - public void addCachedClient(CachedClient app) { + public void addClient(CachedClient app) { logger.tracev("Adding application {0}", app.getId()); addRevisioned(app.getId(), (Revisioned) app); + clientLookup.put(app.getClientId(), app.getId()); } @Override - public void invalidateCachedApplicationById(String id) { + public void invalidateClientById(String id) { CachedClient client = (CachedClient)invalidateObject(id); - if (client != null) logger.tracev("Removing application {0}", client.getClientId()); + if (client != null) { + logger.tracev("Removing application {0}", client.getClientId()); + clientLookup.remove(client.getClientId()); + } } @Override - public void evictCachedApplicationById(String id) { + public void evictClientById(String id) { logger.tracev("Evicting application {0}", id); cache.evict(id); } @@ -205,18 +222,11 @@ public class LockingRealmCache implements RealmCache { } @Override - public void addCachedGroup(CachedGroup role) { + public void addGroup(CachedGroup role) { logger.tracev("Adding group {0}", role.getId()); addRevisioned(role.getId(), (Revisioned) role); } - @Override - public void invalidateCachedGroupById(String id) { - logger.tracev("Removing group {0}", id); - invalidateObject(id); - - } - @Override public void invalidateGroupById(String id) { logger.tracev("Removing group {0}", id); @@ -241,23 +251,17 @@ public class LockingRealmCache implements RealmCache { } @Override - public void evictCachedRoleById(String id) { + public void evictRoleById(String id) { logger.tracev("Evicting role {0}", id); cache.evict(id); } @Override - public void addCachedRole(CachedRole role) { + public void addRole(CachedRole role) { logger.tracev("Adding role {0}", role.getId()); addRevisioned(role.getId(), (Revisioned) role); } - @Override - public void invalidateCachedRoleById(String id) { - logger.tracev("Removing role {0}", id); - invalidateObject(id); - } - @Override public CachedClientTemplate getClientTemplate(String id) { return get(id, CachedClientTemplate.class); @@ -270,19 +274,19 @@ public class LockingRealmCache implements RealmCache { } @Override - public void addCachedClientTemplate(CachedClientTemplate app) { + public void addClientTemplate(CachedClientTemplate app) { logger.tracev("Adding client template {0}", app.getId()); addRevisioned(app.getId(), (Revisioned) app); } @Override - public void invalidateCachedClientTemplateById(String id) { + public void invalidateClientTemplateById(String id) { logger.tracev("Removing client template {0}", id); invalidateObject(id); } @Override - public void evictCachedClientTemplateById(String id) { + public void evictClientTemplateById(String id) { logger.tracev("Evicting client template {0}", id); cache.evict(id); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java index 86bc5a224f..55b6087e09 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java @@ -176,6 +176,17 @@ public class JpaRealmProvider implements RealmProvider { return new ClientAdapter(realm, em, session, app); } + @Override + public ClientModel getClientByClientId(String clientId, RealmModel realm) { + TypedQuery query = em.createNamedQuery("findClientByClientId", ClientEntity.class); + query.setParameter("clientId", clientId); + query.setParameter("realm", realm.getId()); + List results = query.getResultList(); + if (results.isEmpty()) return null; + ClientEntity entity = results.get(0); + return new ClientAdapter(realm, em, session, entity); + } + @Override public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) { ClientTemplateEntity app = em.find(ClientTemplateEntity.class, id); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 4d632ec14d..eb03e53476 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -811,7 +811,7 @@ public class RealmAdapter implements RealmModel { @Override public ClientModel getClientByClientId(String clientId) { - return getClientNameMap().get(clientId); + return session.realms().getClientByClientId(clientId, this); } private static final String BROWSER_HEADER_PREFIX = "_browser_header."; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java index 15544c62ed..5466a7773f 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java @@ -50,6 +50,8 @@ import java.util.Set; @Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "CLIENT_ID"})}) @NamedQueries({ @NamedQuery(name="getClientsByRealm", query="select client from ClientEntity client where client.realm = :realm"), + @NamedQuery(name="findClientIdByClientId", query="select client.id from ClientEntity client where client.clientId = :clientId and client.realm.id = :realm"), + @NamedQuery(name="findClientByClientId", query="select client from ClientEntity client where client.clientId = :clientId and client.realm.id = :realm"), }) public class ClientEntity { diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java index 323bbbe81c..ddfbdefba2 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java @@ -162,6 +162,17 @@ public class MongoRealmProvider implements RealmProvider { return new ClientAdapter(session, realm, appData, invocationContext); } + @Override + public ClientModel getClientByClientId(String clientId, RealmModel realm) { + DBObject query = new QueryBuilder() + .and("realmId").is(realm.getId()) + .and("clientId").is(clientId) + .get(); + MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext); + return appEntity == null ? null : new ClientAdapter(session, realm, appEntity, invocationContext); + + } + @Override public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) { MongoClientTemplateEntity appData = getMongoStore().loadEntity(MongoClientTemplateEntity.class, id, invocationContext); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index bae4589b33..ca7626c3ae 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -807,12 +807,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public ClientModel getClientByClientId(String clientId) { - DBObject query = new QueryBuilder() - .and("realmId").is(getId()) - .and("clientId").is(clientId) - .get(); - MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext); - return appEntity == null ? null : new ClientAdapter(session, this, appEntity, invocationContext); + return session.realms().getClientByClientId(clientId, this); } @Override diff --git a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java index ad9e2d1e9f..59568a3fc9 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java @@ -35,8 +35,11 @@ public interface RealmProvider extends Provider { RealmModel getRealm(String id); RealmModel getRealmByName(String name); - RoleModel getRoleById(String id, RealmModel realm); ClientModel getClientById(String id, RealmModel realm); + ClientModel getClientByClientId(String clientId, RealmModel realm); + + + RoleModel getRoleById(String id, RealmModel realm); ClientTemplateModel getClientTemplateById(String id, RealmModel realm); GroupModel getGroupById(String id, RealmModel realm); diff --git a/server-spi/src/main/java/org/keycloak/models/cache/RealmCache.java b/server-spi/src/main/java/org/keycloak/models/cache/RealmCache.java index 909223b936..2b7b339daf 100755 --- a/server-spi/src/main/java/org/keycloak/models/cache/RealmCache.java +++ b/server-spi/src/main/java/org/keycloak/models/cache/RealmCache.java @@ -30,35 +30,33 @@ import org.keycloak.models.cache.entities.CachedRole; public interface RealmCache { void clear(); - CachedRealm getCachedRealm(String id); + CachedRealm getRealm(String id); - void invalidateCachedRealm(CachedRealm realm); + void invalidateRealm(CachedRealm realm); - void addCachedRealm(CachedRealm realm); + void addRealm(CachedRealm realm); - CachedRealm getCachedRealmByName(String name); + CachedRealm getRealmByName(String name); - void invalidateCachedRealmById(String id); + void invalidateRealmById(String id); - CachedClient getApplication(String id); + CachedClient getClient(String id); - void invalidateApplication(CachedClient app); + void invalidateClient(CachedClient app); - void evictCachedApplicationById(String id); + void evictClientById(String id); - void addCachedClient(CachedClient app); + void addClient(CachedClient app); - void invalidateCachedApplicationById(String id); + void invalidateClientById(String id); CachedRole getRole(String id); void invalidateRole(CachedRole role); - void evictCachedRoleById(String id); + void evictRoleById(String id); - void addCachedRole(CachedRole role); - - void invalidateCachedRoleById(String id); + void addRole(CachedRole role); void invalidateRoleById(String id); @@ -66,9 +64,7 @@ public interface RealmCache { void invalidateGroup(CachedGroup role); - void addCachedGroup(CachedGroup role); - - void invalidateCachedGroupById(String id); + void addGroup(CachedGroup role); void invalidateGroupById(String id); @@ -76,10 +72,10 @@ public interface RealmCache { void invalidateClientTemplate(CachedClientTemplate app); - void evictCachedClientTemplateById(String id); + void evictClientTemplateById(String id); - void addCachedClientTemplate(CachedClientTemplate app); + void addClientTemplate(CachedClientTemplate app); - void invalidateCachedClientTemplateById(String id); + void invalidateClientTemplateById(String id); } diff --git a/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedClient.java index ca3e35ba31..727cabcd66 100755 --- a/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedClient.java +++ b/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedClient.java @@ -127,7 +127,7 @@ public class CachedClient implements Serializable { protected void cacheRoles(RealmCache cache, RealmModel realm, ClientModel model) { for (RoleModel role : model.getRoles()) { roles.put(role.getName(), role.getId()); - cache.addCachedRole(new CachedClientRole(id, role, realm)); + cache.addRole(new CachedClientRole(id, role, realm)); } } diff --git a/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java index 42ed3bcb39..29b93318bd 100755 --- a/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java +++ b/server-spi/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java @@ -39,6 +39,10 @@ import org.keycloak.models.cache.RealmCache; import org.keycloak.common.util.MultivaluedHashMap; import java.io.Serializable; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -89,8 +93,11 @@ public class CachedRealm implements Serializable { protected PasswordPolicy passwordPolicy; protected OTPPolicy otpPolicy; + protected transient PublicKey publicKey; protected String publicKeyPem; + protected transient PrivateKey privateKey; protected String privateKeyPem; + protected transient X509Certificate certificate; protected String certificatePem; protected String codeSecret; @@ -179,8 +186,11 @@ public class CachedRealm implements Serializable { otpPolicy = model.getOTPPolicy(); publicKeyPem = model.getPublicKeyPem(); + publicKey = model.getPublicKey(); privateKeyPem = model.getPrivateKeyPem(); + privateKey = model.getPrivateKey(); certificatePem = model.getCertificatePem(); + certificate = model.getCertificate(); codeSecret = model.getCodeSecret(); loginTheme = model.getLoginTheme(); @@ -265,7 +275,7 @@ public class CachedRealm implements Serializable { for (ClientTemplateModel template : model.getClientTemplates()) { clientTemplates.add(template.getId()); CachedClientTemplate cachedClient = new CachedClientTemplate(cache, delegate, model, template); - cache.addCachedClientTemplate(cachedClient); + cache.addClientTemplate(cachedClient); } } @@ -273,7 +283,7 @@ public class CachedRealm implements Serializable { for (ClientModel client : model.getClients()) { clients.put(client.getClientId(), client.getId()); CachedClient cachedClient = new CachedClient(cache, delegate, model, client); - cache.addCachedClient(cachedClient); + cache.addClient(cachedClient); } } @@ -281,7 +291,7 @@ public class CachedRealm implements Serializable { for (RoleModel role : model.getRoles()) { realmRoles.put(role.getName(), role.getId()); CachedRole cachedRole = new CachedRealmRole(role, model); - cache.addCachedRole(cachedRole); + cache.addRole(cachedRole); } } @@ -584,4 +594,16 @@ public class CachedRealm implements Serializable { public List getClientTemplates() { return clientTemplates; } + + public PublicKey getPublicKey() { + return publicKey; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } + + public X509Certificate getCertificate() { + return certificate; + } } diff --git a/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java b/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java index c1f0a6b02f..cfc9cd5af9 100755 --- a/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java +++ b/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java @@ -88,9 +88,9 @@ public class MaxRateExecutor { StressTest stressTest = future.get(); if (i < jobs - threads - 5) completionService.submit(stressTest); } + long end = System.currentTimeMillis() - start; executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); - long end = System.currentTimeMillis() - start; RateResult rate = new RateResult(result, threads, end); return rate; } @@ -116,10 +116,10 @@ public class MaxRateExecutor { public void printResult(RateResult result) { System.out.println("Threads: " + result.getThreads()); System.out.println("Total Time: " + result.getTime()); + System.out.println("Rate: " + ((double)result.getResult().getIterations()) / ((double)result.getTime())); System.out.println("Successes: " + result.getResult().getSuccess()); System.out.println("Iterations: " + result.getResult().getIterations()); - System.out.println("Average time: " + result.getResult().getAverageTime()); - System.out.println("Rate: " + result.getResult().getRate()); + System.out.println("Average time per iteration: " + result.getResult().getAverageTime()); } @@ -127,7 +127,7 @@ public class MaxRateExecutor { for (RateResult result : allResults) { System.out.println("*******************"); - printSummary(); + printSummary(result); } } public void printSummary(RateResult result) { diff --git a/testsuite/stress/src/test/java/org/keycloak/test/LoginLogoutTest.java b/testsuite/stress/src/test/java/org/keycloak/test/LoginLogoutTest.java index 1348c644d4..351f8f442e 100755 --- a/testsuite/stress/src/test/java/org/keycloak/test/LoginLogoutTest.java +++ b/testsuite/stress/src/test/java/org/keycloak/test/LoginLogoutTest.java @@ -88,8 +88,9 @@ Rate: 0.030480835174883793 } }; MaxRateExecutor executor = new MaxRateExecutor(); - executor.best(factory, 4); + executor.best(factory, 10); executor.printResults(); + executor.printSummary(); } }