Reject bootstrapping endpoints that are already in the ring with different gossip data Patch by Tyler Hobbs, reviewed by brandonwilliams for CASSANDRA-5571
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/4155afd5 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/4155afd5 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/4155afd5 Branch: refs/heads/trunk Commit: 4155afd510828770c2d666a7e4cea28062964130 Parents: 8a06958 Author: Brandon Williams <brandonwilli...@apache.org> Authored: Tue Oct 22 16:44:35 2013 -0500 Committer: Brandon Williams <brandonwilli...@apache.org> Committed: Tue Oct 22 16:44:35 2013 -0500 ---------------------------------------------------------------------- src/java/org/apache/cassandra/gms/Gossiper.java | 2 +- .../cassandra/service/StorageService.java | 30 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/4155afd5/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 c97a54b..07c21bd 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -864,7 +864,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean subscriber.onJoin(ep, epState); } - private boolean isDeadState(EndpointState epState) + public boolean isDeadState(EndpointState epState) { if (epState.getApplicationState(ApplicationState.STATUS) == null) return false; http://git-wip-us.apache.org/repos/asf/cassandra/blob/4155afd5/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 f171192..f9126c7 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -408,6 +408,22 @@ public class StorageService extends NotificationBroadcasterSupport implements IE } } + public synchronized void checkForEndpointCollision() throws ConfigurationException + { + logger.debug("Starting shadow gossip round to check for endpoint collision"); + MessagingService.instance().listen(FBUtilities.getLocalAddress()); + Gossiper.instance.doShadowRound(); + EndpointState epState = Gossiper.instance.getEndpointStateForEndpoint(FBUtilities.getBroadcastAddress()); + if (epState != null && !Gossiper.instance.isDeadState(epState)) + { + 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.", + FBUtilities.getBroadcastAddress())); + } + MessagingService.instance().shutdown(); + Gossiper.instance.resetEndpointStateMap(); + } + public synchronized void initClient() throws ConfigurationException { // We don't wait, because we're going to actually try to work on @@ -564,6 +580,11 @@ public class StorageService extends NotificationBroadcasterSupport implements IE } } + private boolean shouldBootstrap() + { + return DatabaseDescriptor.isAutoBootstrap() && !SystemKeyspace.bootstrapComplete() && !DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress()); + } + private void joinTokenRing(int delay) throws ConfigurationException { joined = true; @@ -581,6 +602,11 @@ public class StorageService extends NotificationBroadcasterSupport implements IE appStates.put(ApplicationState.STATUS, valueFactory.hibernate(true)); appStates.put(ApplicationState.TOKENS, valueFactory.tokens(tokens)); } + else if (shouldBootstrap()) + { + checkForEndpointCollision(); + } + // have to start the gossip service before we can see any info on other nodes. this is necessary // for bootstrap to get the load info it needs. // (we won't be part of the storage ring though until we add a counterId to our state, below.) @@ -621,9 +647,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE SystemKeyspace.bootstrapInProgress(), SystemKeyspace.bootstrapComplete(), DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress())); - if (DatabaseDescriptor.isAutoBootstrap() - && !SystemKeyspace.bootstrapComplete() - && !DatabaseDescriptor.getSeeds().contains(FBUtilities.getBroadcastAddress())) + if (shouldBootstrap()) { if (SystemKeyspace.bootstrapInProgress()) logger.warn("Detected previous bootstrap failure; retrying");