Search in sources :

Example 11 with UserSessionEntity

use of org.keycloak.models.sessions.infinispan.entities.UserSessionEntity in project keycloak by keycloak.

the class ConcurrencyJDGCacheReplaceTest method main.

public static void main(String[] args) throws Exception {
    Cache<String, SessionEntityWrapper<UserSessionEntity>> cache1 = createManager(1).getCache(InfinispanConnectionProvider.USER_SESSION_CACHE_NAME);
    Cache<String, SessionEntityWrapper<UserSessionEntity>> cache2 = createManager(2).getCache(InfinispanConnectionProvider.USER_SESSION_CACHE_NAME);
    // Create initial item
    UserSessionEntity session = new UserSessionEntity();
    session.setId("123");
    session.setRealmId("foo");
    session.setBrokerSessionId("!23123123");
    session.setBrokerUserId(null);
    session.setUser("foo");
    session.setLoginUsername("foo");
    session.setIpAddress("123.44.143.178");
    session.setStarted(Time.currentTime());
    session.setLastSessionRefresh(Time.currentTime());
    AuthenticatedClientSessionEntity clientSession = new AuthenticatedClientSessionEntity(UUID.randomUUID());
    clientSession.setAuthMethod("saml");
    clientSession.setAction("something");
    clientSession.setTimestamp(1234);
    session.getAuthenticatedClientSessions().put(CLIENT_1_UUID.toString(), clientSession.getId());
    SessionEntityWrapper<UserSessionEntity> wrappedSession = new SessionEntityWrapper<>(session);
    // Some dummy testing of remoteStore behaviour
    logger.info("Before put");
    cache1.getAdvancedCache().withFlags(// will still invoke remoteStore . Just doesn't propagate to cluster
    Flag.CACHE_MODE_LOCAL).put("123", wrappedSession);
    logger.info("After put");
    cache1.replace("123", wrappedSession);
    logger.info("After replace");
    cache1.get("123");
    logger.info("After cache1.get");
    cache2.get("123");
    logger.info("After cache2.get");
    cache1.get("123");
    logger.info("After cache1.get - second call");
    cache2.get("123");
    logger.info("After cache2.get - second call");
    cache2.replace("123", wrappedSession);
    logger.info("After replace - second call");
    cache1.get("123");
    logger.info("After cache1.get - third call");
    cache2.get("123");
    logger.info("After cache2.get - third call");
    cache1.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD).entrySet().stream().forEach(e -> {
    });
    logger.info("After cache1.stream");
    // Explicitly call put on remoteCache (KcRemoteCache.write ignores remote writes)
    InfinispanUtil.getRemoteCache(cache1).put("123", session);
    InfinispanUtil.getRemoteCache(cache2).replace("123", session);
    // Create caches, listeners and finally worker threads
    remoteCache1 = InfinispanUtil.getRemoteCache(cache1);
    remoteCache2 = InfinispanUtil.getRemoteCache(cache2);
    // Manual test of lifespans
    testLifespans();
    Thread worker1 = createWorker(cache1, 1);
    Thread worker2 = createWorker(cache2, 2);
    long start = System.currentTimeMillis();
    // Start and join workers
    worker1.start();
    worker2.start();
    worker1.join();
    worker2.join();
    long took = System.currentTimeMillis() - start;
    // // Output
    // for (Map.Entry<String, EntryInfo> entry : state.entrySet()) {
    // System.out.println(entry.getKey() + ":::" + entry.getValue());
    // worker1.cache.remove(entry.getKey());
    // }
    System.out.println("Finished. Took: " + took + " ms. Notes: " + cache1.get("123").getEntity().getNotes().size() + ", successfulListenerWrites: " + successfulListenerWrites.get() + ", successfulListenerWrites2: " + successfulListenerWrites2.get() + ", failedReplaceCounter: " + failedReplaceCounter.get() + ", failedReplaceCounter2: " + failedReplaceCounter2.get());
    System.out.println("Sleeping before other report");
    Thread.sleep(2000);
    System.out.println("Finished. Took: " + took + " ms. Notes: " + cache1.get("123").getEntity().getNotes().size() + ", successfulListenerWrites: " + successfulListenerWrites.get() + ", successfulListenerWrites2: " + successfulListenerWrites2.get() + ", failedReplaceCounter: " + failedReplaceCounter.get() + ", failedReplaceCounter2: " + failedReplaceCounter2.get());
    System.out.println("remoteCache1.notes: " + ((UserSessionEntity) remoteCache1.get("123")).getNotes().size());
    System.out.println("remoteCache2.notes: " + ((UserSessionEntity) remoteCache2.get("123")).getNotes().size());
    System.out.println("Histogram: ");
    // shutdown pools
    for (ExecutorService ex : executors) {
        ex.shutdown();
    }
    // Finish JVM
    cache1.getCacheManager().stop();
    cache2.getCacheManager().stop();
}
Also used : AuthenticatedClientSessionEntity(org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity) ExecutorService(java.util.concurrent.ExecutorService) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper) UserSessionEntity(org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)

Example 12 with UserSessionEntity

use of org.keycloak.models.sessions.infinispan.entities.UserSessionEntity in project keycloak by keycloak.

the class UserSessionAdapter method restartSession.

@Override
public void restartSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId) {
    UserSessionUpdateTask task = new UserSessionUpdateTask() {

        @Override
        public void runUpdate(UserSessionEntity entity) {
            provider.updateSessionEntity(entity, realm, user, loginUsername, ipAddress, authMethod, rememberMe, brokerSessionId, brokerUserId);
            entity.setState(null);
            entity.getNotes().clear();
            entity.getAuthenticatedClientSessions().clear();
        }
    };
    update(task);
}
Also used : UserSessionUpdateTask(org.keycloak.models.sessions.infinispan.changes.UserSessionUpdateTask) UserSessionEntity(org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)

Example 13 with UserSessionEntity

use of org.keycloak.models.sessions.infinispan.entities.UserSessionEntity in project keycloak by keycloak.

the class UserSessionAdapter method removeNote.

@Override
public void removeNote(String name) {
    UserSessionUpdateTask task = new UserSessionUpdateTask() {

        @Override
        public void runUpdate(UserSessionEntity entity) {
            entity.getNotes().remove(name);
        }
    };
    update(task);
}
Also used : UserSessionUpdateTask(org.keycloak.models.sessions.infinispan.changes.UserSessionUpdateTask) UserSessionEntity(org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)

Example 14 with UserSessionEntity

use of org.keycloak.models.sessions.infinispan.entities.UserSessionEntity in project keycloak by keycloak.

the class UserSessionAdapter method removeAuthenticatedClientSessions.

@Override
public void removeAuthenticatedClientSessions(Collection<String> removedClientUUIDS) {
    if (removedClientUUIDS == null || removedClientUUIDS.isEmpty()) {
        return;
    }
    // an invalid session is handled as nonexistent in UserSessionAdapter.getAuthenticatedClientSessions()
    if (removedClientUUIDS.size() >= MINIMUM_INACTIVE_CLIENT_SESSIONS_TO_CLEANUP) {
        // Update user session
        UserSessionUpdateTask task = new UserSessionUpdateTask() {

            @Override
            public void runUpdate(UserSessionEntity entity) {
                removedClientUUIDS.forEach(entity.getAuthenticatedClientSessions()::remove);
            }
        };
        update(task);
    }
    // do not iterate the removedClientUUIDS and remove the clientSession directly as the addTask can manipulate
    // the collection being iterated, and that can lead to unpredictable behaviour (e.g. NPE)
    List<UUID> clientSessionUuids = removedClientUUIDS.stream().map(entity.getAuthenticatedClientSessions()::get).filter(Objects::nonNull).collect(Collectors.toList());
    clientSessionUuids.forEach(clientSessionId -> this.clientSessionUpdateTx.addTask(clientSessionId, Tasks.removeSync()));
}
Also used : UserSessionUpdateTask(org.keycloak.models.sessions.infinispan.changes.UserSessionUpdateTask) UUID(java.util.UUID) UserSessionEntity(org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)

Example 15 with UserSessionEntity

use of org.keycloak.models.sessions.infinispan.entities.UserSessionEntity in project keycloak by keycloak.

the class UserSessionAdapter method setLastSessionRefresh.

public void setLastSessionRefresh(int lastSessionRefresh) {
    if (offline) {
        // Received the message from the other DC that we should update the lastSessionRefresh in local cluster. Don't update DB in that case.
        // The other DC already did.
        Boolean ignoreRemoteCacheUpdate = (Boolean) session.getAttribute(CrossDCLastSessionRefreshListener.IGNORE_REMOTE_CACHE_UPDATE);
        if (ignoreRemoteCacheUpdate == null || !ignoreRemoteCacheUpdate) {
            provider.getPersisterLastSessionRefreshStore().putLastSessionRefresh(session, entity.getId(), realm.getId(), lastSessionRefresh);
        }
    }
    UserSessionUpdateTask task = new UserSessionUpdateTask() {

        @Override
        public void runUpdate(UserSessionEntity entity) {
            entity.setLastSessionRefresh(lastSessionRefresh);
        }

        @Override
        public CrossDCMessageStatus getCrossDCMessageStatus(SessionEntityWrapper<UserSessionEntity> sessionWrapper) {
            return new CrossDCLastSessionRefreshChecker(provider.getLastSessionRefreshStore(), provider.getOfflineLastSessionRefreshStore()).shouldSaveUserSessionToRemoteCache(UserSessionAdapter.this.session, UserSessionAdapter.this.realm, sessionWrapper, offline, lastSessionRefresh);
        }

        @Override
        public String toString() {
            return "setLastSessionRefresh(" + lastSessionRefresh + ')';
        }
    };
    update(task);
}
Also used : UserSessionUpdateTask(org.keycloak.models.sessions.infinispan.changes.UserSessionUpdateTask) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper) CrossDCLastSessionRefreshChecker(org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshChecker) UserSessionEntity(org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)

Aggregations

UserSessionEntity (org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)27 SessionEntityWrapper (org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper)13 AuthenticatedClientSessionEntity (org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity)9 UserSessionUpdateTask (org.keycloak.models.sessions.infinispan.changes.UserSessionUpdateTask)6 UUID (java.util.UUID)5 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 OfflineUserSessionModel (org.keycloak.models.OfflineUserSessionModel)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 RemoteCache (org.infinispan.client.hotrod.RemoteCache)4 Cache (org.infinispan.Cache)3 HotRodClientException (org.infinispan.client.hotrod.exceptions.HotRodClientException)3 UserSessionModel (org.keycloak.models.UserSessionModel)3 Serializable (java.io.Serializable)2 Collection (java.util.Collection)2 Collections (java.util.Collections)2 Iterator (java.util.Iterator)2 Objects (java.util.Objects)2 Set (java.util.Set)2