Search in sources :

Example 6 with RemoteCache

use of org.infinispan.client.hotrod.RemoteCache in project keycloak by keycloak.

the class RemoteCacheSessionListener method replaceRemoteEntityInCache.

protected void replaceRemoteEntityInCache(K key, long eventVersion) {
    // TODO can be optimized and remoteSession sent in the event itself?
    AtomicBoolean replaced = new AtomicBoolean(false);
    int replaceRetries = 0;
    int sleepInterval = 25;
    do {
        replaceRetries++;
        SessionEntityWrapper<V> localEntityWrapper = cache.get(key);
        VersionedValue<SessionEntityWrapper<V>> remoteSessionVersioned = remoteCache.getWithMetadata(key);
        // Probably already removed
        if (remoteSessionVersioned == null || remoteSessionVersioned.getValue() == null) {
            logger.debugf("Entity '%s' not present in remoteCache. Ignoring replace", key);
            return;
        }
        if (remoteSessionVersioned.getVersion() < eventVersion) {
            try {
                logger.debugf("Got replace remote entity event prematurely for entity '%s', will try again. Event version: %d, got: %d", key, eventVersion, remoteSessionVersioned == null ? -1 : remoteSessionVersioned.getVersion());
                // using exponential backoff
                Thread.sleep(new Random().nextInt(sleepInterval));
                continue;
            } catch (InterruptedException ex) {
                continue;
            } finally {
                sleepInterval = sleepInterval << 1;
            }
        }
        SessionEntity remoteSession = remoteSessionVersioned.getValue().getEntity();
        logger.debugf("Read session entity from the remote cache: %s . replaceRetries=%d", remoteSession, replaceRetries);
        SessionEntityWrapper<V> sessionWrapper = remoteSession.mergeRemoteEntityWithLocalEntity(localEntityWrapper);
        KeycloakModelUtils.runJobInTransaction(sessionFactory, (session -> {
            RealmModel realm = session.realms().getRealm(sessionWrapper.getEntity().getRealmId());
            long lifespanMs = lifespanMsLoader.apply(realm, sessionWrapper.getEntity());
            long maxIdleTimeMs = maxIdleTimeMsLoader.apply(realm, sessionWrapper.getEntity());
            // We received event from remoteCache, so we won't update it back
            replaced.set(cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_STORE, Flag.SKIP_CACHE_LOAD, Flag.IGNORE_RETURN_VALUES).replace(key, localEntityWrapper, sessionWrapper, lifespanMs, TimeUnit.MILLISECONDS, maxIdleTimeMs, TimeUnit.MILLISECONDS));
        }));
        if (!replaced.get()) {
            logger.debugf("Did not succeed in merging sessions, will try again: %s", remoteSession);
        }
    } while (replaceRetries < MAXIMUM_REPLACE_RETRIES && !replaced.get());
}
Also used : KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) Logger(org.jboss.logging.Logger) BiFunction(java.util.function.BiFunction) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientEvent(org.infinispan.client.hotrod.event.ClientEvent) Random(java.util.Random) Cache(org.infinispan.Cache) RemoteCache(org.infinispan.client.hotrod.RemoteCache) ClientCacheEntryCreated(org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated) ExecutorsProvider(org.keycloak.executors.ExecutorsProvider) TopologyInfo(org.keycloak.connections.infinispan.TopologyInfo) SessionEntity(org.keycloak.models.sessions.infinispan.entities.SessionEntity) ClientCacheEntryCreatedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent) InfinispanUtil(org.keycloak.connections.infinispan.InfinispanUtil) ExecutorService(java.util.concurrent.ExecutorService) RealmModel(org.keycloak.models.RealmModel) ClientListener(org.infinispan.client.hotrod.annotation.ClientListener) KeycloakSession(org.keycloak.models.KeycloakSession) ClientCacheEntryRemoved(org.infinispan.client.hotrod.annotation.ClientCacheEntryRemoved) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper) TimeUnit(java.util.concurrent.TimeUnit) VersionedValue(org.infinispan.client.hotrod.VersionedValue) ClientCacheEntryModified(org.infinispan.client.hotrod.annotation.ClientCacheEntryModified) Flag(org.infinispan.context.Flag) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) ClientCacheEntryModifiedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent) ClientCacheEntryRemovedEvent(org.infinispan.client.hotrod.event.ClientCacheEntryRemovedEvent) RealmModel(org.keycloak.models.RealmModel) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Random(java.util.Random) SessionEntity(org.keycloak.models.sessions.infinispan.entities.SessionEntity) SessionEntityWrapper(org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper)

Example 7 with RemoteCache

use of org.infinispan.client.hotrod.RemoteCache in project keycloak by keycloak.

the class ConcurrencyJDGCachePutTest method getClusterStartupTime.

public static int getClusterStartupTime(Cache<String, Integer> cache, String cacheKey, EntryInfo wrapper, int myThreadId) {
    Integer startupTime = myThreadId == 1 ? Integer.valueOf(cacheKey.substring(4)) : Integer.valueOf(cacheKey.substring(4)) * 2;
    // Concurrency doesn't work correctly with this
    // Integer existingClusterStartTime = (Integer) cache.putIfAbsent(cacheKey, startupTime);
    // Concurrency works fine with this
    RemoteCache remoteCache = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(RemoteStore.class).iterator().next().getRemoteCache();
    Integer existingClusterStartTime = null;
    for (int i = 0; i < 10; i++) {
        try {
            existingClusterStartTime = (Integer) remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsent(cacheKey, startupTime);
            break;
        } catch (HotRodClientException ce) {
            if (i == 9) {
                throw ce;
            // break;
            } else {
                wrapper.exceptions.incrementAndGet();
                System.err.println("Exception: i=" + i + " for key: " + cacheKey + " and myThreadId: " + myThreadId);
            }
        }
    }
    if (existingClusterStartTime == null) // || startupTime.equals(remoteCache.get(cacheKey))
    {
        wrapper.successfulInitializations.incrementAndGet();
        return startupTime;
    } else {
        wrapper.failedInitializations.incrementAndGet();
        return existingClusterStartTime;
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RemoteCache(org.infinispan.client.hotrod.RemoteCache) HotRodClientException(org.infinispan.client.hotrod.exceptions.HotRodClientException) RemoteStore(org.infinispan.persistence.remote.RemoteStore)

Example 8 with RemoteCache

use of org.infinispan.client.hotrod.RemoteCache in project keycloak by keycloak.

the class RemoteCacheSessionsLoader method loadSessions.

@Override
public WorkerResult loadSessions(KeycloakSession session, RemoteCacheSessionsLoaderContext loaderContext, WorkerContext ctx) {
    Cache cache = getCache(session);
    Cache decoratedCache = cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE, Flag.IGNORE_RETURN_VALUES);
    RemoteCache remoteCache = getRemoteCache(session);
    Set<Integer> myIspnSegments = getMyIspnSegments(ctx.getSegment(), loaderContext);
    log.debugf("Will do bulk load of sessions from remote cache '%s' . Segment: %d", cache.getName(), ctx.getSegment());
    Map<Object, Object> remoteEntries = new HashMap<>();
    CloseableIterator<Map.Entry> iterator = null;
    int countLoaded = 0;
    try {
        iterator = remoteCache.retrieveEntries(null, myIspnSegments, loaderContext.getSessionsPerSegment());
        while (iterator.hasNext()) {
            countLoaded++;
            Map.Entry entry = iterator.next();
            remoteEntries.put(entry.getKey(), entry.getValue());
        }
    } catch (RuntimeException e) {
        log.warnf(e, "Error loading sessions from remote cache '%s' for segment '%d'", remoteCache.getName(), ctx.getSegment());
        throw e;
    } finally {
        if (iterator != null) {
            iterator.close();
        }
    }
    decoratedCache.putAll(remoteEntries);
    log.debugf("Successfully finished loading sessions from cache '%s' . Segment: %d, Count of sessions loaded: %d", cache.getName(), ctx.getSegment(), countLoaded);
    return new WorkerResult(true, ctx.getSegment(), ctx.getWorkerId());
}
Also used : HashMap(java.util.HashMap) RemoteCache(org.infinispan.client.hotrod.RemoteCache) HashMap(java.util.HashMap) Map(java.util.Map) Cache(org.infinispan.Cache) RemoteCache(org.infinispan.client.hotrod.RemoteCache)

Example 9 with RemoteCache

use of org.infinispan.client.hotrod.RemoteCache in project keycloak by keycloak.

the class RemoteCacheProvider method loadRemoteCache.

protected synchronized RemoteCache loadRemoteCache(String cacheName) {
    RemoteCache remoteCache = InfinispanUtil.getRemoteCache(cacheManager.getCache(cacheName));
    if (remoteCache != null) {
        logger.infof("Hotrod version for remoteCache %s: %s", remoteCache.getName(), remoteCache.getRemoteCacheManager().getConfiguration().version());
    }
    Boolean remoteStoreSecurity = config.getBoolean("remoteStoreSecurityEnabled");
    if (remoteStoreSecurity == null) {
        try {
            logger.debugf("Detecting remote security settings of HotRod server, cache %s. Disable by explicitly setting \"remoteStoreSecurityEnabled\" property in spi=connectionsInfinispan/provider=default", cacheName);
            remoteStoreSecurity = false;
            final RemoteCache<Object, Object> scriptCache = remoteCache.getRemoteCacheManager().getCache(SCRIPT_CACHE_NAME);
            if (scriptCache == null) {
                logger.debug("Cannot detect remote security settings of HotRod server, disabling.");
            } else {
                scriptCache.containsKey("");
            }
        } catch (HotRodClientException ex) {
            logger.debug("Seems that HotRod server requires authentication, enabling.");
            remoteStoreSecurity = true;
        }
    }
    if (remoteStoreSecurity) {
        logger.infof("Remote store security for cache %s is enabled. Disable by setting \"remoteStoreSecurityEnabled\" property to \"false\" in spi=connectionsInfinispan/provider=default", cacheName);
        RemoteCacheManager securedMgr = getOrCreateSecuredRemoteCacheManager(config, cacheName, remoteCache.getRemoteCacheManager());
        return securedMgr.getCache(remoteCache.getName());
    } else {
        logger.infof("Remote store security for cache %s is disabled. If server fails to connect to remote JDG server, enable it.", cacheName);
        return remoteCache;
    }
}
Also used : RemoteCacheManager(org.infinispan.client.hotrod.RemoteCacheManager) RemoteCache(org.infinispan.client.hotrod.RemoteCache) HotRodClientException(org.infinispan.client.hotrod.exceptions.HotRodClientException)

Example 10 with RemoteCache

use of org.infinispan.client.hotrod.RemoteCache in project keycloak by keycloak.

the class CrossDCAwareCacheFactory method getFactory.

static CrossDCAwareCacheFactory getFactory(Cache<String, Serializable> workCache, Set<RemoteStore> remoteStores) {
    if (remoteStores.isEmpty()) {
        logger.debugf("No configured remoteStore available. Cross-DC scenario is not used");
        return new InfinispanCacheWrapperFactory(workCache);
    } else {
        logger.debugf("RemoteStore is available. Cross-DC scenario will be used");
        if (remoteStores.size() > 1) {
            logger.warnf("More remoteStores configured for work cache. Will use just the first one");
        }
        // For cross-DC scenario, we need to return underlying remoteCache for atomic operations to work properly
        RemoteStore remoteStore = remoteStores.iterator().next();
        RemoteCache remoteCache = remoteStore.getRemoteCache();
        if (remoteCache == null) {
            String cacheName = remoteStore.getConfiguration().remoteCacheName();
            throw new IllegalStateException("Remote cache '" + cacheName + "' is not available.");
        }
        return new RemoteCacheWrapperFactory(remoteCache);
    }
}
Also used : RemoteCache(org.infinispan.client.hotrod.RemoteCache) RemoteStore(org.infinispan.persistence.remote.RemoteStore)

Aggregations

RemoteCache (org.infinispan.client.hotrod.RemoteCache)26 SessionEntityWrapper (org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper)9 Cache (org.infinispan.Cache)8 Map (java.util.Map)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 HotRodClientException (org.infinispan.client.hotrod.exceptions.HotRodClientException)5 RemoteStore (org.infinispan.persistence.remote.RemoteStore)5 UUID (java.util.UUID)4 BasicCache (org.infinispan.commons.api.BasicCache)4 Logger (org.jboss.logging.Logger)4 KeycloakSession (org.keycloak.models.KeycloakSession)4 RealmModel (org.keycloak.models.RealmModel)4 UserSessionEntity (org.keycloak.models.sessions.infinispan.entities.UserSessionEntity)4 HashMap (java.util.HashMap)3 Objects (java.util.Objects)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 TimeUnit (java.util.concurrent.TimeUnit)3 BiFunction (java.util.function.BiFunction)3 Function (java.util.function.Function)3 Collectors (java.util.stream.Collectors)3