From ab87c03732fa4f7d76ca5a1d1d8b78bd679e7601 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Fri, 13 Jun 2014 19:39:20 -0400 Subject: [PATCH] cache 1st iteration finished --- .../models/cache/CacheKeycloakSessionSpi.java | 2 +- .../models/cache/NoCacheKeycloakSession.java | 281 ++++++++++++++++++ .../cache/NoCacheKeycloakSessionFactory.java | 30 ++ ...k.models.cache.CacheKeycloakSessionFactory | 3 +- .../model/test/AbstractModelTest.java | 8 +- .../aerogear-ups/auth-server/pom.xml | 5 + .../main/webapp/WEB-INF/keycloak-server.json | 4 + server/pom.xml | 5 + .../resources/META-INF/keycloak-server.json | 4 + .../resources/META-INF/keycloak-server.json | 4 + .../testsuite/perf/AccessTokenPerfTest.java | 6 +- 11 files changed, 343 insertions(+), 9 deletions(-) create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSession.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSessionFactory.java diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java index f0b53a44e4..7e4e8e6144 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java @@ -12,7 +12,7 @@ public class CacheKeycloakSessionSpi implements Spi { @Override public String getName() { - return "cacheKeycloakSession"; + return "modelCache"; } @Override diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSession.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSession.java new file mode 100755 index 0000000000..afc35e30d3 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSession.java @@ -0,0 +1,281 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakTransaction; +import org.keycloak.models.OAuthClientModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.UserSessionModel; +import org.keycloak.models.UsernameLoginFailureModel; +import org.keycloak.models.cache.entities.CachedApplication; +import org.keycloak.models.cache.entities.CachedApplicationRole; +import org.keycloak.models.cache.entities.CachedOAuthClient; +import org.keycloak.models.cache.entities.CachedRealm; +import org.keycloak.models.cache.entities.CachedRealmRole; +import org.keycloak.models.cache.entities.CachedRole; +import org.keycloak.provider.ProviderSession; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class NoCacheKeycloakSession implements CacheKeycloakSession { + protected ProviderSession providerSession; + protected KeycloakSession sessionDelegate; + protected KeycloakTransaction transactionDelegate; + protected boolean transactionActive; + protected boolean setRollbackOnly; + + public NoCacheKeycloakSession(ProviderSession providerSession) { + this.providerSession = providerSession; + } + + @Override + public KeycloakSession getDelegate() { + if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction"); + if (sessionDelegate != null) return sessionDelegate; + sessionDelegate = providerSession.getProvider(KeycloakSession.class); + transactionDelegate = sessionDelegate.getTransaction(); + if (!transactionDelegate.isActive()) { + transactionDelegate.begin(); + if (setRollbackOnly) { + transactionDelegate.setRollbackOnly(); + } + } + return sessionDelegate; + } + + @Override + public void registerRealmInvalidation(String id) { + } + + @Override + public void registerApplicationInvalidation(String id) { + } + + @Override + public void registerRoleInvalidation(String id) { + } + + @Override + public void registerOAuthClientInvalidation(String id) { + } + + @Override + public KeycloakTransaction getTransaction() { + return new KeycloakTransaction() { + @Override + public void begin() { + transactionActive = true; + } + + @Override + public void commit() { + if (sessionDelegate == null) return; + try { + sessionDelegate.getTransaction().commit(); + } finally { + } + } + + @Override + public void rollback() { + setRollbackOnly = true; + if (sessionDelegate == null) return; + try { + sessionDelegate.getTransaction().rollback(); + } finally { + } + } + + @Override + public void setRollbackOnly() { + setRollbackOnly = true; + if (sessionDelegate == null) return; + sessionDelegate.getTransaction().setRollbackOnly(); + setRollbackOnly = true; + } + + @Override + public boolean getRollbackOnly() { + return setRollbackOnly; + } + + @Override + public boolean isActive() { + return transactionActive; + } + }; + } + + @Override + public RealmModel createRealm(String name) { + return getDelegate().createRealm(name); + } + + @Override + public RealmModel createRealm(String id, String name) { + return getDelegate().createRealm(id, name); + } + + @Override + public RealmModel getRealm(String id) { + return getDelegate().getRealm(id); + } + + @Override + public RealmModel getRealmByName(String name) { + return getDelegate().getRealmByName(name); + } + + @Override + public UserModel getUserById(String id, RealmModel realm) { + return getDelegate().getUserById(id, realm); + } + + @Override + public UserModel getUserByUsername(String username, RealmModel realm) { + return getDelegate().getUserByUsername(username, realm); + } + + @Override + public UserModel getUserByEmail(String email, RealmModel realm) { + return getDelegate().getUserByEmail(email, realm); + } + + @Override + public List getRealms() { + // we don't cache this for now + return getDelegate().getRealms(); + } + + @Override + public boolean removeRealm(String id) { + return getDelegate().removeRealm(id); + } + + @Override + public void removeAllData() { + getDelegate().removeAllData(); + } + + @Override + public void close() { + if (sessionDelegate != null) sessionDelegate.close(); + } + + @Override + public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { + return getDelegate().getUserBySocialLink(socialLink, realm); + } + + @Override + public List getUsers(RealmModel realm) { + return getDelegate().getUsers(realm); + } + + @Override + public List searchForUser(String search, RealmModel realm) { + return getDelegate().searchForUser(search, realm); + } + + @Override + public List searchForUserByAttributes(Map attributes, RealmModel realm) { + return getDelegate().searchForUserByAttributes(attributes, realm); + } + + @Override + public Set getSocialLinks(UserModel user, RealmModel realm) { + return getDelegate().getSocialLinks(user, realm); + } + + @Override + public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { + return getDelegate().getSocialLink(user, socialProvider, realm); + } + + @Override + public RoleModel getRoleById(String id, RealmModel realm) { + return getDelegate().getRoleById(id, realm); + } + + @Override + public ApplicationModel getApplicationById(String id, RealmModel realm) { + return getDelegate().getApplicationById(id, realm); + } + + @Override + public OAuthClientModel getOAuthClientById(String id, RealmModel realm) { + return getDelegate().getOAuthClientById(id, realm); + } + + @Override + public UsernameLoginFailureModel getUserLoginFailure(String username, RealmModel realm) { + return getDelegate().getUserLoginFailure(username, realm); + } + + @Override + public UsernameLoginFailureModel addUserLoginFailure(String username, RealmModel realm) { + return getDelegate().addUserLoginFailure(username, realm); + } + + @Override + public List getAllUserLoginFailures(RealmModel realm) { + return getDelegate().getAllUserLoginFailures(realm); + } + + @Override + public UserSessionModel createUserSession(RealmModel realm, UserModel user, String ipAddress) { + return getDelegate().createUserSession(realm, user, ipAddress); + } + + @Override + public UserSessionModel getUserSession(String id, RealmModel realm) { + return getDelegate().getUserSession(id, realm); + } + + @Override + public List getUserSessions(UserModel user, RealmModel realm) { + return getDelegate().getUserSessions(user, realm); + } + + @Override + public Set getUserSessions(RealmModel realm, ClientModel client) { + return getDelegate().getUserSessions(realm, client); + } + + @Override + public int getActiveUserSessions(RealmModel realm, ClientModel client) { + return getDelegate().getActiveUserSessions(realm, client); + } + + @Override + public void removeUserSession(UserSessionModel session) { + getDelegate().removeUserSession(session); + } + + @Override + public void removeUserSessions(RealmModel realm, UserModel user) { + getDelegate().removeUserSessions(realm, user); + } + + @Override + public void removeExpiredUserSessions(RealmModel realm) { + getDelegate().removeExpiredUserSessions(realm); + } + + @Override + public void removeUserSessions(RealmModel realm) { + getDelegate().removeUserSessions(realm); + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSessionFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSessionFactory.java new file mode 100755 index 0000000000..d3691a420c --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheKeycloakSessionFactory.java @@ -0,0 +1,30 @@ +package org.keycloak.models.cache; + +import org.keycloak.Config; +import org.keycloak.provider.ProviderSession; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class NoCacheKeycloakSessionFactory implements CacheKeycloakSessionFactory { + @Override + public CacheKeycloakSession create(ProviderSession providerSession) { + return new NoCacheKeycloakSession(providerSession); + } + + @Override + public void close() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void init(Config.Scope config) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getId() { + return "none"; + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory index 0cf4453cbe..57939b6b76 100755 --- a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory +++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory @@ -1 +1,2 @@ -org.keycloak.models.cache.SimpleCacheKeycloakSessionFactory \ No newline at end of file +org.keycloak.models.cache.SimpleCacheKeycloakSessionFactory +org.keycloak.models.cache.NoCacheKeycloakSessionFactory \ No newline at end of file diff --git a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java index 5366d04527..3d61794eb7 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java @@ -40,7 +40,7 @@ public class AbstractModelTest { providerSessionFactory = KeycloakApplication.createProviderSessionFactory(); ProviderSession providerSession = providerSessionFactory.createSession(); - KeycloakSession identitySession = providerSession.getProvider(CacheKeycloakSession.class); + KeycloakSession identitySession = providerSession.getProvider(CacheKeycloakSession.class, "simple"); try { identitySession.getTransaction().begin(); new ApplianceBootstrap().bootstrap(identitySession, "/auth"); @@ -59,7 +59,7 @@ public class AbstractModelTest { public void before() throws Exception { providerSession = providerSessionFactory.createSession(); - identitySession = providerSession.getProvider(CacheKeycloakSession.class); + identitySession = providerSession.getProvider(CacheKeycloakSession.class, "simple"); identitySession.getTransaction().begin(); realmManager = new RealmManager(identitySession); } @@ -70,7 +70,7 @@ public class AbstractModelTest { providerSession.close(); providerSession = providerSessionFactory.createSession(); - identitySession = providerSession.getProvider(CacheKeycloakSession.class); + identitySession = providerSession.getProvider(CacheKeycloakSession.class, "simple"); try { identitySession.getTransaction().begin(); @@ -105,7 +105,7 @@ public class AbstractModelTest { providerSession.close(); providerSession = providerSessionFactory.createSession(); - identitySession = providerSession.getProvider(CacheKeycloakSession.class); + identitySession = providerSession.getProvider(CacheKeycloakSession.class, "simple"); identitySession.getTransaction().begin(); realmManager = new RealmManager(identitySession); } diff --git a/project-integrations/aerogear-ups/auth-server/pom.xml b/project-integrations/aerogear-ups/auth-server/pom.xml index 349dd1388b..07ec63136e 100755 --- a/project-integrations/aerogear-ups/auth-server/pom.xml +++ b/project-integrations/aerogear-ups/auth-server/pom.xml @@ -47,6 +47,11 @@ keycloak-model-api ${project.version} + + org.keycloak + keycloak-invalidation-cache-model + ${project.version} + org.keycloak keycloak-model-jpa diff --git a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/keycloak-server.json b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/keycloak-server.json index 33b4c94817..e321f7f013 100755 --- a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/keycloak-server.json +++ b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/keycloak-server.json @@ -7,6 +7,10 @@ "provider": "jpa" }, + "modelCache": { + "provider": "${keycloak.model.cache.provider:simple}" + }, + "timer": { "provider": "basic" }, diff --git a/server/pom.xml b/server/pom.xml index 849c862297..9185e34a3b 100755 --- a/server/pom.xml +++ b/server/pom.xml @@ -42,6 +42,11 @@ keycloak-model-api ${project.version} + + org.keycloak + keycloak-invalidation-cache-model + ${project.version} + org.keycloak keycloak-model-jpa diff --git a/server/src/main/resources/META-INF/keycloak-server.json b/server/src/main/resources/META-INF/keycloak-server.json index 7bc7ffd591..23752151a0 100755 --- a/server/src/main/resources/META-INF/keycloak-server.json +++ b/server/src/main/resources/META-INF/keycloak-server.json @@ -14,6 +14,10 @@ "provider": "jpa" }, + "modelCache": { + "provider": "${keycloak.model.cache.provider:simple}" + }, + "timer": { "provider": "basic" }, diff --git a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json index bc3370f53e..a1e1ec17ff 100755 --- a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json +++ b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json @@ -23,6 +23,10 @@ } }, + "modelCache": { + "provider": "${keycloak.model.cache.provider:simple}" + }, + "timer": { "provider": "basic" }, diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java index 91027d3553..ca22ebddf5 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java @@ -234,7 +234,7 @@ public class AccessTokenPerfTest { @Test public void perfJaxrsClientLogin() { - long ITERATIONS = 10; + long ITERATIONS = 100; JaxrsClientLogin login = new JaxrsClientLogin(); long start = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { @@ -248,7 +248,7 @@ public class AccessTokenPerfTest { @Test public void perfBrowserLogin() { - long ITERATIONS = 10; + long ITERATIONS = 100; long start = System.currentTimeMillis(); BrowserLogin login = new BrowserLogin(); for (int i = 0; i < ITERATIONS; i++) { @@ -260,7 +260,7 @@ public class AccessTokenPerfTest { @Test public void multiThread() throws Exception { - int num_threads = 10; + int num_threads = 20; Thread[] threads = new Thread[num_threads]; for (int i = 0; i < num_threads; i++) { threads[i] = new Thread(new Runnable() {