org.infinispan
infinispan-component-annotations
diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/TopologyInfo.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/TopologyInfo.java
index c1470bab8be..c339e9002fd 100644
--- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/TopologyInfo.java
+++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/TopologyInfo.java
@@ -28,9 +28,7 @@ import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.GlobalComponentRegistry;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
-import org.infinispan.remoting.transport.LocalModeAddress;
import org.infinispan.remoting.transport.Transport;
-import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.jboss.logging.Logger;
import org.jgroups.stack.IpAddress;
@@ -116,12 +114,9 @@ public class TopologyInfo {
public boolean amIOwner(Cache, ?> cache, Object key) {
Address myAddress = cache.getCacheManager().getAddress();
Address objectOwnerAddress = getOwnerAddress(cache, key);
-
- // NOTE: For scattered caches, this will always return true, which may not be correct. Need to review this if we add support for scattered caches
return Objects.equals(myAddress, objectOwnerAddress);
}
-
/**
* Get route to be used as the identifier for sticky session. Return null if I am not able to find the appropriate route (or in case of local mode)
* @deprecated Use {@link org.keycloak.sessions.StickySessionEncoderProvider#sessionIdRoute(String)} instead.
@@ -140,11 +135,11 @@ public class TopologyInfo {
Address address = getOwnerAddress(cache, key);
// Local mode
- if (address == null || (address == LocalModeAddress.INSTANCE)) {
+ if (address == null || (address == Address.LOCAL)) {
return myNodeName;
}
- org.jgroups.Address jgroupsAddress = toJGroupsAddress(address);
+ org.jgroups.Address jgroupsAddress = Address.toExtendedUUID(address);
String name = NameCache.get(jgroupsAddress);
// If no logical name exists, create one using physical address
@@ -169,16 +164,4 @@ public class TopologyInfo {
DistributionManager dist = cache.getAdvancedCache().getDistributionManager();
return dist == null ? cache.getCacheManager().getAddress() : dist.getCacheTopology().getDistribution(key).primary();
}
-
-
- // See org.wildfly.clustering.server.group.CacheGroup
- private static org.jgroups.Address toJGroupsAddress(Address address) {
- if ((address == null) || (address == LocalModeAddress.INSTANCE)) return null;
- if (address instanceof JGroupsAddress jgroupsAddress) {
- return jgroupsAddress.getJGroupsAddress();
- }
- throw new IllegalArgumentException(address.toString());
- }
-
-
}
diff --git a/model/infinispan/src/main/java/org/keycloak/jgroups/protocol/KEYCLOAK_JDBC_PING2.java b/model/infinispan/src/main/java/org/keycloak/jgroups/protocol/KEYCLOAK_JDBC_PING2.java
index c69fe31b96a..f6c25d21408 100644
--- a/model/infinispan/src/main/java/org/keycloak/jgroups/protocol/KEYCLOAK_JDBC_PING2.java
+++ b/model/infinispan/src/main/java/org/keycloak/jgroups/protocol/KEYCLOAK_JDBC_PING2.java
@@ -18,222 +18,18 @@
package org.keycloak.jgroups.protocol;
import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.List;
import java.util.Objects;
-import java.util.stream.Collectors;
import org.keycloak.connections.jpa.JpaConnectionProviderFactory;
-import org.jgroups.Address;
-import org.jgroups.Event;
-import org.jgroups.PhysicalAddress;
-import org.jgroups.View;
import org.jgroups.protocols.JDBC_PING2;
import org.jgroups.protocols.PingData;
-import org.jgroups.stack.Protocol;
-import org.jgroups.util.ExtendedUUID;
-import org.jgroups.util.NameCache;
-import org.jgroups.util.Responses;
import org.jgroups.util.UUID;
-/**
- * Enhanced JDBC_PING2 to handle entries transactionally.
- *
- * Workaround for issue JGRP-2870
- */
public class KEYCLOAK_JDBC_PING2 extends JDBC_PING2 {
private JpaConnectionProviderFactory factory;
- @Override
- protected void handleView(View new_view, View old_view, boolean coord_changed) {
- // If we are the coordinator, it is good to learn about new entries that have been added before we delete them.
- // If we are not the coordinator, it is good to learn the new entries added by the coordinator.
- // This avoids a "JGRP000032: %s: no physical address for %s, dropping message" that leads to split clusters at concurrent startup.
- learnExistingAddresses();
-
- // This is an updated logic where we do not call removeAll but instead remove those obsolete entries.
- // This avoids the short moment where the table is empty and a new node might not see any other node.
- if (is_coord) {
- if (remove_old_coords_on_view_change) {
- Address old_coord = old_view != null ? old_view.getCreator() : null;
- if (old_coord != null)
- remove(cluster_name, old_coord);
- }
- Address[] left = View.diff(old_view, new_view)[1];
- if (coord_changed || update_store_on_view_change || left.length > 0) {
- writeAll(left);
- if (remove_all_data_on_view_change) {
- removeAllNotInCurrentView();
- }
- if (remove_all_data_on_view_change || remove_old_coords_on_view_change) {
- startInfoWriter();
- }
- }
- } else if (coord_changed && !remove_all_data_on_view_change) {
- // I'm no longer the coordinator, usually due to a merge.
- // The new coordinator will update my status to non-coordinator, and remove me fully
- // if 'remove_all_data_on_view_change' is enabled and I'm no longer part of the view.
- // Maybe this branch even be removed completely, but for JDBC_PING 'remove_all_data_on_view_change' is always set to true.
- PhysicalAddress physical_addr = (PhysicalAddress) down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr));
- PingData coord_data = new PingData(local_addr, true, NameCache.get(local_addr), physical_addr).coord(is_coord);
- write(Collections.singletonList(coord_data), cluster_name);
- }
- }
-
- @Override
- protected void removeAll(String clustername) {
- // This is unsafe as even if we would fill the table a moment later, a new node might see an empty table and become a coordinator
- throw new RuntimeException("Not implemented as it is unsafe");
- }
-
- private void removeAllNotInCurrentView() {
- try {
- List list = readFromDB(getClusterName());
- for (PingData data : list) {
- Address addr = data.getAddress();
- if (view != null && !view.containsMember(addr)) {
- addDiscoveryResponseToCaches(addr, data.getLogicalName(), data.getPhysicalAddr());
- remove(cluster_name, addr);
- }
- }
- } catch (Exception e) {
- log.error(String.format("%s: failed reading from the DB", local_addr), e);
- }
- }
-
- protected void learnExistingAddresses() {
- try {
- List list = readFromDB(getClusterName());
- for (PingData data : list) {
- Address addr = data.getAddress();
- if (local_addr != null && !local_addr.equals(addr)) {
- addDiscoveryResponseToCaches(addr, data.getLogicalName(), data.getPhysicalAddr());
- }
- }
- } catch (Exception e) {
- log.error(String.format("%s: failed reading from the DB", local_addr), e);
- }
- }
-
- @Override
- public synchronized boolean isInfoWriterRunning() {
- // Do not rely on the InfoWriter, instead always write the missing information on find if it is missing. Find is also triggered by MERGE.
- return false;
- }
-
- @Override
- public void findMembers(List members, boolean initial_discovery, Responses responses) {
- if (initial_discovery) {
- try {
- List pingData = readFromDB(cluster_name);
- PhysicalAddress physical_addr = (PhysicalAddress) down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr));
- // Sending the discovery here, as parent class will not execute it once there is data in the table
- sendDiscoveryResponse(local_addr, physical_addr, NameCache.get(local_addr), null, is_coord);
- PingData coord_data = new PingData(local_addr, true, NameCache.get(local_addr), physical_addr).coord(is_coord);
- write(Collections.singletonList(coord_data), cluster_name);
- while (pingData.stream().noneMatch(PingData::isCoord)) {
- // Do a quick check if more nodes have arrived, to have a more complete list of nodes to start with.
- List newPingData = readFromDB(cluster_name);
- if (newPingData.stream().map(PingData::getAddress).collect(Collectors.toSet()).equals(pingData.stream().map(PingData::getAddress).collect(Collectors.toSet()))
- || pingData.stream().anyMatch(PingData::isCoord)) {
- break;
- }
- pingData = newPingData;
- }
- } catch (Exception e) {
- log.error(String.format("%s: failed reading from the DB", local_addr), e);
- }
- }
-
- super.findMembers(members, initial_discovery, responses);
- }
-
- @Override
- protected void writeToDB(PingData data, String clustername) throws SQLException {
- lock.lock();
- try (Connection connection = getConnection()) {
- if(call_insert_sp != null && insert_sp != null)
- callInsertStoredProcedure(connection, data, clustername);
- else {
- boolean isAutocommit = connection.getAutoCommit();
- try {
- if (isAutocommit) {
- // Always use a transaction for the delete+insert to make it atomic
- // to avoid the short moment where there is no entry in the table.
- connection.setAutoCommit(false);
- } else {
- log.warn("Autocommit is disabled. This indicates a transaction context that might batch statements and can lead to deadlocks.");
- }
- delete(connection, clustername, data.getAddress());
- insert(connection, data, clustername);
- if (isAutocommit) {
- connection.commit();
- }
- } catch (SQLException e) {
- if (isAutocommit) {
- connection.rollback();
- }
- throw e;
- } finally {
- if (isAutocommit) {
- connection.setAutoCommit(true);
- }
- }
- }
- } finally {
- lock.unlock();
- }
-
- }
-
- /* START: JDBC_PING2 does not handle ExtendedUUID yet, see
- https://github.com/belaban/JGroups/pull/901 - until this is backported, we convert all of them.
- */
-
- @Override
- public T addr(Address addr) {
- addr = toUUID(addr);
- return super.addr(addr);
- }
-
- @Override
- public T setAddress(Address addr) {
- addr = toUUID(addr);
- return super.setAddress(addr);
- }
-
- @Override
- protected void delete(Connection conn, String clustername, Address addressToDelete) throws SQLException {
- super.delete(conn, clustername, toUUID(addressToDelete));
- }
-
- @Override
- protected void delete(String clustername, Address addressToDelete) throws SQLException {
- super.delete(clustername, toUUID(addressToDelete));
- }
-
- @Override
- protected void insert(Connection connection, PingData data, String clustername) throws SQLException {
- if (data.getAddress() instanceof ExtendedUUID) {
- data = new PingData(toUUID(data.getAddress()), data.isServer(), data.getLogicalName(), data.getPhysicalAddr()).coord(data.isCoord());
- }
- super.insert(connection, data, clustername);
- }
-
- private static Address toUUID(Address addr) {
- if (addr instanceof ExtendedUUID eUUID) {
- addr = new UUID(eUUID.getMostSignificantBits(), eUUID.getLeastSignificantBits());
- }
- return addr;
- }
-
- /* END: JDBC_PING2 does not handle ExtendedUUID yet, see
- https://github.com/belaban/JGroups/pull/901 - until this is backported, we convert all of them.
- */
-
@Override
protected void loadDriver() {
//no-op, using JpaConnectionProviderFactory
diff --git a/model/infinispan/src/main/java/org/keycloak/marshalling/KeycloakModelSchema.java b/model/infinispan/src/main/java/org/keycloak/marshalling/KeycloakModelSchema.java
index 771db6d9887..fc5262ed571 100644
--- a/model/infinispan/src/main/java/org/keycloak/marshalling/KeycloakModelSchema.java
+++ b/model/infinispan/src/main/java/org/keycloak/marshalling/KeycloakModelSchema.java
@@ -118,6 +118,7 @@ import org.infinispan.protostream.types.java.CommonTypes;
schemaPackageName = Marshalling.PROTO_SCHEMA_PACKAGE,
schemaFilePath = "proto/generated",
allowNullFields = true,
+ orderedMarshallers = true,
// common-types for UUID
dependsOn = CommonTypes.class,
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanStickySessionEncoderProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanStickySessionEncoderProviderFactory.java
index fabbc3a7da4..ea13e83b3a2 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanStickySessionEncoderProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanStickySessionEncoderProviderFactory.java
@@ -34,7 +34,7 @@ import org.keycloak.sessions.StickySessionEncoderProvider;
import org.keycloak.sessions.StickySessionEncoderProviderFactory;
import org.infinispan.Cache;
-import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
+import org.infinispan.remoting.transport.Address;
import org.jboss.logging.Logger;
import org.jgroups.util.NameCache;
@@ -153,6 +153,6 @@ public class InfinispanStickySessionEncoderProviderFactory implements StickySess
// Return null if the logical name is not available yet.
// The following request may be redirected to the wrong instance, but that's ok.
// In a healthy/stable cluster, the name cache is correctly populated.
- return primaryOwner instanceof JGroupsAddress jgrpAddr ? NameCache.get(jgrpAddr.getJGroupsAddress()) : null;
+ return primaryOwner == null ? null : NameCache.get(Address.toExtendedUUID(primaryOwner));
}
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/QueryHelper.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/QueryHelper.java
index 6289369fa10..54850c04ec7 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/QueryHelper.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/query/QueryHelper.java
@@ -32,7 +32,7 @@ import java.util.stream.StreamSupport;
import org.infinispan.client.hotrod.impl.query.RemoteQuery;
import org.infinispan.commons.api.query.Query;
-import org.infinispan.query.dsl.QueryResult;
+import org.infinispan.commons.api.query.QueryResult;
public final class QueryHelper {
@@ -195,7 +195,7 @@ public final class QueryHelper {
return;
}
currentOffset += resultList.size();
- if (rsp.count().isExact() && currentOffset >= rsp.count().value()) {
+ if (rsp.count().exact() && currentOffset >= rsp.count().value()) {
completed = true;
return;
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java
index 84ae02f9401..ab18675a087 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remote/RemoteUserSessionProvider.java
@@ -439,10 +439,10 @@ public class RemoteUserSessionProvider implements UserSessionProvider {
private Stream streamUserSessionByClientId(RealmModel realm, String clientId, boolean offline, Integer offset, Integer maxResults) {
var userSessionIdQuery = ClientSessionQueries.fetchUserSessionIdForClientId(getClientSessionTransaction(offline).getCache(), realm.getId(), clientId);
- if (offset != null) {
+ if (offset != null && offset > -1) {
userSessionIdQuery.startOffset(offset);
}
- userSessionIdQuery.maxResults(maxResults == null ? Integer.MAX_VALUE : maxResults);
+ userSessionIdQuery.maxResults(maxResults == null || maxResults == -1 ? Integer.MAX_VALUE : maxResults);
var userSessionTx = getUserSessionTransaction(offline);
return Flowable.fromIterable(QueryHelper.toCollection(userSessionIdQuery, QueryHelper.SINGLE_PROJECTION_TO_STRING))
.flatMapMaybe(userSessionTx::maybeGet, false, MAX_CONCURRENT_REQUESTS)
diff --git a/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/CacheConfigurator.java b/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/CacheConfigurator.java
index 62c942d74b2..489fe371a39 100644
--- a/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/CacheConfigurator.java
+++ b/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/CacheConfigurator.java
@@ -33,6 +33,7 @@ import org.keycloak.models.sessions.infinispan.entities.RemoteUserSessionEntity;
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
import org.infinispan.commons.dataconversion.MediaType;
+import org.infinispan.commons.util.TimeQuantity;
import org.infinispan.configuration.cache.AbstractStoreConfiguration;
import org.infinispan.configuration.cache.BackupConfiguration;
import org.infinispan.configuration.cache.BackupFailurePolicy;
@@ -394,13 +395,17 @@ public final class CacheConfigurator {
}
private static ConfigurationBuilder remoteCacheConfigurationBuilder(String name, Config.Scope config, String[] sites, Class> indexedEntity, long expirationWakeupPeriodMillis) {
+ return remoteCacheConfigurationBuilder(name, config, sites, indexedEntity, TimeQuantity.valueOf(expirationWakeupPeriodMillis));
+ }
+
+ private static ConfigurationBuilder remoteCacheConfigurationBuilder(String name, Config.Scope config, String[] sites, Class> indexedEntity, TimeQuantity expirationWakeupPeriod) {
var builder = new ConfigurationBuilder();
builder.clustering().cacheMode(CacheMode.DIST_SYNC);
builder.clustering().hash().numOwners(Math.max(MIN_NUM_OWNERS_REMOTE_CACHE, config.getInt(numOwnerConfigKey(name), MIN_NUM_OWNERS_REMOTE_CACHE)));
builder.clustering().stateTransfer().chunkSize(STATE_TRANSFER_CHUNK_SIZE);
builder.encoding().mediaType(MediaType.APPLICATION_PROTOSTREAM);
builder.statistics().enable();
- builder.expiration().enableReaper().wakeUpInterval(expirationWakeupPeriodMillis);
+ builder.expiration().enableReaper().wakeUpInterval(expirationWakeupPeriod.longValue());
if (indexedEntity != null) {
builder.indexing().enable().addIndexedEntities(Marshalling.protoEntity(indexedEntity));
diff --git a/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/DefaultCacheEmbeddedConfigProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/DefaultCacheEmbeddedConfigProviderFactory.java
index cc4f8991e7a..835a51058fb 100644
--- a/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/DefaultCacheEmbeddedConfigProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/spi/infinispan/impl/embedded/DefaultCacheEmbeddedConfigProviderFactory.java
@@ -241,8 +241,8 @@ public class DefaultCacheEmbeddedConfigProviderFactory implements CacheEmbeddedC
.meterRegistry(Metrics.globalRegistry);
builder.cacheContainer().statistics(true);
builder.metrics()
- .namesAsTags(true)
- .histograms(keycloakConfig.getBoolean(HISTOGRAMS, Boolean.FALSE));
+ .histograms(keycloakConfig.getBoolean(HISTOGRAMS, Boolean.FALSE))
+ .legacy(true);
holder.getNamedConfigurationBuilders()
.values()
.stream()
diff --git a/model/infinispan/src/main/resources/default-configs/default-keycloak-jgroups-udp.xml b/model/infinispan/src/main/resources/default-configs/default-keycloak-jgroups-udp.xml
deleted file mode 100644
index 9f6d6bf0376..00000000000
--- a/model/infinispan/src/main/resources/default-configs/default-keycloak-jgroups-udp.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/operator/src/test/resources/cache-ispn.xml b/operator/src/test/resources/cache-ispn.xml
index b3920d7cf8c..4a845d5378e 100644
--- a/operator/src/test/resources/cache-ispn.xml
+++ b/operator/src/test/resources/cache-ispn.xml
@@ -18,8 +18,8 @@
+ xsi:schemaLocation="urn:infinispan:config:16.0 https://infinispan.org/schemas/infinispan-config-16.0.xsd"
+ xmlns="urn:infinispan:config:16.0">
diff --git a/pom.xml b/pom.xml
index 20d1f0be379..ca559805cc2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,9 +91,9 @@
2.4.240
6.2.13.Final
6.2.13.Final
- 15.0.19.Final
9.0.1.Final
- 5.0.14.Final
+ 16.0.5
+ 6.0.3
${protostream.version}
diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml
index 54bfaa67657..c92b7a387f4 100644
--- a/quarkus/runtime/pom.xml
+++ b/quarkus/runtime/pom.xml
@@ -672,16 +672,6 @@
infinispan-component-annotations
provided
-
-