keycloak-aplcache

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
index 2a0b436..c6d3814 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
@@ -215,7 +215,9 @@ public class InfinispanChangelogBasedTransaction<K, V extends SessionEntity> ext
 
             // Replace fail. Need to load latest entity from cache, apply updates again and try to replace in cache again
             if (!replaced) {
-                logger.debugf("Replace failed for entity: %s . Will try again", key);
+                if (logger.isDebugEnabled()) {
+                    logger.debugf("Replace failed for entity: %s, old version %s, new version %s. Will try again", key, oldVersionEntity.getVersion(), newVersionEntity.getVersion());
+                }
 
                 oldVersionEntity = cache.get(key);
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
index bb74f4f..3400782 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
@@ -184,13 +184,16 @@ public class SessionEntityWrapper<S extends SessionEntity> {
 
             if (forTransport) {
                 final SessionEntity entity = (SessionEntity) input.readObject();
-                log.debugf("Loaded entity from remote store: %s", entity);
-                return new SessionEntityWrapper(entity);
+                final SessionEntityWrapper res = new SessionEntityWrapper(entity);
+                if (log.isDebugEnabled()) {
+                    log.debugf("Loaded entity from remote store: %s, version=%s, metadata=%s", entity, res.version, res.localMetadata);
+                }
+                return res;
             } else {
                 UUID sessionVersion = new UUID(input.readLong(), input.readLong());
                 HashMap<String, String> map = MarshallUtil.unmarshallMap(input, HashMap::new);
                 final SessionEntity entity = (SessionEntity) input.readObject();
-                log.debugf("Found entity locally: %s", entity);
+                log.debugf("Found entity locally: entity=%s, version=%s, metadata=%s", entity, sessionVersion, map);
                 return new SessionEntityWrapper(sessionVersion, map, entity);
             }
         }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
index 898648a..18d892f 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
@@ -135,6 +135,28 @@ public class AuthenticatedClientSessionEntity extends SessionEntity {
         return id;
     }
 
+    @Override
+    public String toString() {
+        return "AuthenticatedClientSessionEntity [" + "id=" + id + ']';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof AuthenticatedClientSessionEntity)) return false;
+
+        AuthenticatedClientSessionEntity that = (AuthenticatedClientSessionEntity) o;
+
+        if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
+
     public static class ExternalizerImpl implements Externalizer<AuthenticatedClientSessionEntity> {
 
         @Override
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/SessionEntity.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/SessionEntity.java
index 6d93e19..9f45069 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/SessionEntity.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/SessionEntity.java
@@ -22,6 +22,11 @@ import java.io.Serializable;
 import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
 
 /**
+ * Represents an entity containing data about a session, i.e. an object that is stored in infinispan cache and can be
+ * potentially shared across DCs. Due to conflict management in {@code RemoteCacheInvoker} and
+ * {@code InfinispanChangelogBasedTransaction} that use Infinispan's {@code replace()} method, overriding {@link #hashCode()}
+ * and {@link #equals(java.lang.Object)} is <b>mandatory</b> in descendants.
+ *
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public abstract class SessionEntity implements Serializable {
@@ -55,4 +60,10 @@ public abstract class SessionEntity implements Serializable {
         }
     };
 
+    @Override
+    public abstract boolean equals(Object obj);
+
+    @Override
+    public abstract int hashCode();
+
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InitializerState.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InitializerState.java
index 3efd76b..930b24e 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InitializerState.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InitializerState.java
@@ -26,6 +26,7 @@ import java.io.ObjectOutput;
 import java.util.BitSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Objects;
 import org.infinispan.commons.marshall.Externalizer;
 import org.infinispan.commons.marshall.MarshallUtil;
 import org.infinispan.commons.marshall.SerializeWith;
@@ -123,6 +124,43 @@ public class InitializerState extends SessionEntity {
           + (", non-finished segments count: " + nonFinished);
     }
 
+    @Override
+    public int hashCode() {
+        int hash = 3;
+        hash = 97 * hash + this.sessionsCount;
+        hash = 97 * hash + this.segmentsCount;
+        hash = 97 * hash + Objects.hashCode(this.segments);
+        hash = 97 * hash + this.lowestUnfinishedSegment;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final InitializerState other = (InitializerState) obj;
+        if (this.sessionsCount != other.sessionsCount) {
+            return false;
+        }
+        if (this.segmentsCount != other.segmentsCount) {
+            return false;
+        }
+        if (this.lowestUnfinishedSegment != other.lowestUnfinishedSegment) {
+            return false;
+        }
+        if ( ! Objects.equals(this.segments, other.segments)) {
+            return false;
+        }
+        return true;
+    }
+
     public static class ExternalizerImpl implements Externalizer<InitializerState> {
 
         private static final int VERSION_1 = 1;