From bb2c16c677b0f5ace6f6721069e8c21a584e33f9 Mon Sep 17 00:00:00 2001 From: Benedict Elliott Smith Date: Sun, 15 Jan 2023 12:20:12 +0000 Subject: [PATCH] EndpointState is mutable, so we must copy it before trying to serialize patch by Benedict Elliott Smith; reviewed by Mick Semb Wever for CASSANDRA-18164 --- CHANGES.txt | 1 + src/java/org/apache/cassandra/gms/Gossiper.java | 8 ++++++++ src/java/org/apache/cassandra/service/paxos/Paxos.java | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3c63353f72..1352d00b26 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.1.1 + * Fix PAXOS2_COMMIT_AND_PREPARE_RSP serialisation AssertionError (CASSANDRA-18164) * Streaming progress virtual table lock contention can trigger TCP_USER_TIMEOUT and fail streaming (CASSANDRA-18110) * Fix perpetual load of denylist on read in cases where denylist can never be loaded (CASSANDRA-18116) Merged from 4.0: diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 4a46ca3040..d43cf115f8 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -1139,6 +1139,14 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return endpointStateMap.get(ep); } + public EndpointState copyEndpointStateForEndpoint(InetAddressAndPort ep) + { + EndpointState epState = endpointStateMap.get(ep); + if (epState == null) + return null; + return new EndpointState(epState); + } + public ImmutableSet getEndpoints() { return ImmutableSet.copyOf(endpointStateMap.keySet()); diff --git a/src/java/org/apache/cassandra/service/paxos/Paxos.java b/src/java/org/apache/cassandra/service/paxos/Paxos.java index ee5b27e407..5bdb75c78f 100644 --- a/src/java/org/apache/cassandra/service/paxos/Paxos.java +++ b/src/java/org/apache/cassandra/service/paxos/Paxos.java @@ -1156,8 +1156,8 @@ public class Paxos return emptyMap(); Map endpoints = Maps.newHashMapWithExpectedSize(remoteElectorate.size() + localElectorate.size()); - remoteElectorate.forEach(host -> endpoints.put(host, Gossiper.instance.getEndpointStateForEndpoint(host))); - localElectorate.forEach(host -> endpoints.putIfAbsent(host, Gossiper.instance.getEndpointStateForEndpoint(host))); + remoteElectorate.forEach(host -> endpoints.put(host, Gossiper.instance.copyEndpointStateForEndpoint(host))); + localElectorate.forEach(host -> endpoints.putIfAbsent(host, Gossiper.instance.copyEndpointStateForEndpoint(host))); return endpoints; }