checkForEndpointCollision fails for legitimate collisions, improved version after CR, CASSANDRA-9765
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/54470a25 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/54470a25 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/54470a25 Branch: refs/heads/trunk Commit: 54470a25f3c3c9ce6cb600c798ddcfe5e3962768 Parents: 2c9b490 Author: Stefania Alborghetti <[email protected]> Authored: Wed Jul 15 16:30:22 2015 +0800 Committer: Stefania Alborghetti <[email protected]> Committed: Wed Jul 15 16:30:22 2015 +0800 ---------------------------------------------------------------------- src/java/org/apache/cassandra/gms/Gossiper.java | 35 +++++++++++++------- .../cassandra/service/StorageService.java | 3 +- 2 files changed, 24 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/54470a25/src/java/org/apache/cassandra/gms/Gossiper.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 23eff82..8eecc98 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -680,12 +680,8 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean /** * A fat client is a node that has not joined the ring, therefore acting as a coordinator only. - * It possesses no data. This method attempts to determine this property, except that for dead nodes - * we cannot tell. (??) We should also check that the node is not shutdown (and possibly other states) - * but due to fear of breaking things I added a new method to do this, isLiveFatClient(), see - * CASSANDRA-9765 for more information. * - * @param endpoint - the endpoint we need to check + * @param endpoint - the endpoint to check * @return true if it is a fat client */ public boolean isFatClient(InetAddress endpoint) @@ -698,9 +694,29 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return !isDeadState(epState) && !StorageService.instance.getTokenMetadata().isMember(endpoint); } - public boolean isLiveFatClient(InetAddress endpoint) + /** + * Check if this endpoint can safely bootstrap into the cluster. + * + * @param endpoint - the endpoint to check + * @return true if the endpoint can join the cluster + */ + public boolean isSafeForBootstrap(InetAddress endpoint) { - return isFatClient(endpoint) && !isShutdownState(endpointStateMap.get(endpoint)); + EndpointState epState = endpointStateMap.get(endpoint); + String state = getApplicationState(epState); + logger.info("{} state : {}", endpoint, state); + + // if there's no previous state, or the node was previously removed from the cluster, we're good + if (epState == null || isDeadState(epState)) + return true; + + // these states are not allowed to join the cluster + List<String> states = new ArrayList<String>() {{ + add(""); // failed bootstrap but we did start gossiping + add(VersionedValue.STATUS_NORMAL); // node is legit in the cluster or was stopped kill -9 + //add(VersionedValue.STATUS_BOOTSTRAPPING); // failed bootstrap + add(VersionedValue.SHUTDOWN); }}; // node was shutdown + return !states.contains(state); } private void doStatusCheck() @@ -1047,11 +1063,6 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean return false; } - public boolean isShutdownState(EndpointState epState) - { - return getApplicationState(epState).equals(VersionedValue.SHUTDOWN); - } - private static String getApplicationState(EndpointState epState) { if (epState == null || epState.getApplicationState(ApplicationState.STATUS) == null) http://git-wip-us.apache.org/repos/asf/cassandra/blob/54470a25/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index d70fff2..745fe4c 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -455,8 +455,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE if (!MessagingService.instance().isListening()) MessagingService.instance().listen(FBUtilities.getLocalAddress()); Gossiper.instance.doShadowRound(); - EndpointState epState = Gossiper.instance.getEndpointStateForEndpoint(FBUtilities.getBroadcastAddress()); - if (epState != null && !Gossiper.instance.isDeadState(epState) && !Gossiper.instance.isLiveFatClient(FBUtilities.getBroadcastAddress())) + if (!Gossiper.instance.isSafeForBootstrap(FBUtilities.getBroadcastAddress())) { throw new RuntimeException(String.format("A node with address %s already exists, cancelling join. " + "Use cassandra.replace_address if you want to replace this node.",
