This is an automated email from the ASF dual-hosted git repository. brandonwilliams pushed a commit to branch CASSANDRA-16588-trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 9f038b877fee83bf1c450171337db602c32c360b Author: Brandon Williams <[email protected]> AuthorDate: Wed Apr 14 13:49:21 2021 -0500 Ignore stale ack in shadow --- src/java/org/apache/cassandra/gms/Gossiper.java | 15 ++++++++ .../org/apache/cassandra/gms/ShadowRoundTest.java | 40 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index b5434aa..923ffc8 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -1969,12 +1969,27 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return (scheduledGossipTask != null) && (!scheduledGossipTask.isCancelled()); } + public boolean isShadowRoundStateMap(Map<InetAddressAndPort, EndpointState> epStateMap) + { + // it is possible for a previously queued ack to be sent to us when we come back up in shadow + EndpointState localState = epStateMap.get(FBUtilities.getBroadcastAddressAndPort()); + if (localState != null && epStateMap.size() == 1) // response only contains our IP + { + logger.debug("Not exiting shadow round because received bogus ACK {} -> {}", FBUtilities.getBroadcastAddressAndPort(), localState); + return false; + } + return true; + } + protected void maybeFinishShadowRound(InetAddressAndPort respondent, boolean isInShadowRound, Map<InetAddressAndPort, EndpointState> epStateMap) { if (inShadowRound) { if (!isInShadowRound) { + if (!isShadowRoundStateMap(epStateMap)) + return; + if (!seeds.contains(respondent)) logger.warn("Received an ack from {}, who isn't a seed. Ensure your seed list includes a live node. Exiting shadow round", respondent); diff --git a/test/unit/org/apache/cassandra/gms/ShadowRoundTest.java b/test/unit/org/apache/cassandra/gms/ShadowRoundTest.java index 2bcbc50..f5d436f 100644 --- a/test/unit/org/apache/cassandra/gms/ShadowRoundTest.java +++ b/test/unit/org/apache/cassandra/gms/ShadowRoundTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.apache.cassandra.config.Config; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.commitlog.CommitLog; @@ -39,6 +40,7 @@ import org.apache.cassandra.net.MockMessagingService; import org.apache.cassandra.net.MockMessagingSpy; import org.apache.cassandra.net.Verb; import org.apache.cassandra.service.StorageService; +import org.apache.cassandra.utils.FBUtilities; import static org.apache.cassandra.net.MockMessagingService.verb; import static org.junit.Assert.assertEquals; @@ -117,4 +119,42 @@ public class ShadowRoundTest assertEquals(0, spyAck2.messagesIntercepted); assertEquals(0, spyMigrationReq.messagesIntercepted); } + + @Test + public void testBadAckInShadow() + { + final AtomicBoolean ackSend = new AtomicBoolean(false); + MockMessagingSpy spySyn = MockMessagingService.when(verb(Verb.GOSSIP_DIGEST_SYN)) + .respondN((msgOut, to) -> + { + // ACK with bad data in shadow round + if (!ackSend.compareAndSet(false, true)) + { + while (!Gossiper.instance.isEnabled()) ; + } + + HeartBeatState hb = new HeartBeatState(123, 456); + EndpointState state = new EndpointState(hb); + GossipDigestAck payload = new GossipDigestAck( + Collections.singletonList(new GossipDigest(FBUtilities.getBroadcastAddressAndPort(), hb.getGeneration(), hb.getHeartBeatVersion())), + Collections.singletonMap(FBUtilities.getBroadcastAddressAndPort(), state)); + + logger.warn("Simulating bad digest ACK reply"); + return Message.builder(Verb.GOSSIP_DIGEST_ACK, payload) + .from(to) + .build(); + }, 1); + + + System.setProperty(Config.PROPERTY_PREFIX + "auto_bootstrap", "false"); + try + { + StorageService.instance.initServer(); + } + catch (Exception e) + { + assertEquals("Unable to gossip with any peers", e.getMessage()); + } + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
