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());
}
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;
}
}
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());
}
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;
}
}
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);
}
}
Aggregations