This is an automated email from the ASF dual-hosted git repository. brandonwilliams pushed a commit to branch CASSANDRA-16588 in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 64a5fff0da3a389ff3ec0155b8472f919171cb20 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 | 37 ++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 69f7fee..5e6adbf 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -1701,12 +1701,27 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return anyNodeOn30; } + public boolean isShadowRoundStateMap(Map<InetAddress, 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.getBroadcastAddress()); + if (localState != null && epStateMap.size() == 1) // response only contains our IP + { + logger.debug("Not exiting shadow round because received bogus ACK {} -> {}", FBUtilities.getBroadcastAddress(), localState); + return false; + } + return true; + } + protected void maybeFinishShadowRound(InetAddress respondent, boolean isInShadowRound, Map<InetAddress, 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 f8cc49c..5ce72b5 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.exceptions.ConfigurationException; @@ -38,6 +39,7 @@ import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.net.MockMessagingService; import org.apache.cassandra.net.MockMessagingSpy; 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; @@ -113,4 +115,39 @@ 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(MessagingService.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.getBroadcastAddress(), hb.getGeneration(), hb.getHeartBeatVersion())), + Collections.singletonMap(FBUtilities.getBroadcastAddress(), state)); + + logger.warn("Simulating digest ACK reply, {}", payload); + return MessageIn.create(to, payload, Collections.emptyMap(), MessagingService.Verb.GOSSIP_DIGEST_ACK, MessagingService.current_version); + }, 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]
