This is an automated email from the ASF dual-hosted git repository.
dcapwell pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new af9439bcd7 IllegalArgumentException in Gossiper#order due to
concurrent mutations to elements being applied
af9439bcd7 is described below
commit af9439bcd781756a0d845215c4c03c5fd8e74b86
Author: David Capwell <[email protected]>
AuthorDate: Mon Oct 10 15:39:52 2022 -0700
IllegalArgumentException in Gossiper#order due to concurrent mutations to
elements being applied
patch by David Capwell; reviewed by Blake Eggleston for CASSANDRA-17908
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/gms/Gossiper.java | 40 +++++++++++++++++--------
2 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index c0a7723887..37ad298e45 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.2
+ * IllegalArgumentException in Gossiper#order due to concurrent mutations to
elements being applied (CASSANDRA-17908)
* Include estimated active compaction remaining write size when starting a
new compaction (CASSANDRA-17931)
* Mixed mode support for internode authentication during TLS upgrades
(CASSANDRA-17923)
* Revert Mockito downgrade from CASSANDRA-17750 (CASSANDRA-17496)
diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java
b/src/java/org/apache/cassandra/gms/Gossiper.java
index d0fab0cac5..d05ef94bea 100644
--- a/src/java/org/apache/cassandra/gms/Gossiper.java
+++ b/src/java/org/apache/cassandra/gms/Gossiper.java
@@ -1528,22 +1528,38 @@ public class Gossiper implements
IFailureDetectionEventListener, GossiperMBean
* In that case above, the {@link Map#entrySet()} ordering can be random,
causing h4 to apply before h2, which will
* be rejected by subscripers (only after updating gossip causing zero
retries).
*/
- private static Comparator<Entry<InetAddressAndPort, EndpointState>>
STATE_MAP_ORDERING =
- ((Comparator<Entry<InetAddressAndPort, EndpointState>>) (e1, e2) -> {
- // check status first, make sure bootstrap status happens-after all
others
- if (BOOTSTRAPPING_STATUS.contains(getGossipStatus(e1.getValue())))
- return 1;
- if (BOOTSTRAPPING_STATUS.contains(getGossipStatus(e2.getValue())))
- return -1;
- return 0;
- })
- .thenComparingInt((Entry<InetAddressAndPort, EndpointState> e) ->
e.getValue().getHeartBeatState().getGeneration())
- .thenComparing(Entry::getKey);
+ private static Comparator<Entry<InetAddressAndPort, EndpointState>>
stateOrderMap()
+ {
+ // There apears to be some edge cases where the state we are ordering
get added to the global state causing
+ // ordering to change... to avoid that rely on a cache
+ // see CASSANDRA-17908
+ class Cache extends HashMap<InetAddressAndPort, EndpointState>
+ {
+ EndpointState get(Entry<InetAddressAndPort, EndpointState> e)
+ {
+ if (containsKey(e.getKey()))
+ return get(e.getKey());
+ put(e.getKey(), new EndpointState(e.getValue()));
+ return get(e.getKey());
+ }
+ }
+ Cache cache = new Cache();
+ return ((Comparator<Entry<InetAddressAndPort, EndpointState>>) (e1,
e2) -> {
+ // check status first, make sure bootstrap status happens-after
all others
+ if (BOOTSTRAPPING_STATUS.contains(getGossipStatus(cache.get(e1))))
+ return 1;
+ if (BOOTSTRAPPING_STATUS.contains(getGossipStatus(cache.get(e2))))
+ return -1;
+ return 0;
+ })
+ .thenComparingInt((Entry<InetAddressAndPort, EndpointState> e) ->
cache.get(e).getHeartBeatState().getGeneration())
+ .thenComparing(Entry::getKey);
+ }
private static Iterable<Entry<InetAddressAndPort, EndpointState>>
order(Map<InetAddressAndPort, EndpointState> epStateMap)
{
List<Entry<InetAddressAndPort, EndpointState>> list = new
ArrayList<>(epStateMap.entrySet());
- Collections.sort(list, STATE_MAP_ORDERING);
+ Collections.sort(list, stateOrderMap());
return list;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]