diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 92f61ff273..fea71b1a73 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -432,6 +432,66 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean } } + /** + * Do not call this method unless you know what you are doing. + * It will try extremely hard to obliterate any endpoint from the ring, + * even if it does not know about it. + * This should only ever be called by human via JMX. + * @param address + * @throws UnknownHostException + */ + public void unsafeAssassinateEndpoint(String address) throws UnknownHostException + { + InetAddress endpoint = InetAddress.getByName(address); + EndpointState epState = endpointStateMap.get(endpoint); + Token token = null; + logger.warn("Assassinating {} via gossip", endpoint); + if (epState == null) + { + epState = new EndpointState(new HeartBeatState((int)((System.currentTimeMillis() + 60000) / 1000), 9999)); + } + else + { + try + { + token = StorageService.instance.getTokenMetadata().getToken(endpoint); + } + catch (AssertionError e) + { + } + int generation = epState.getHeartBeatState().getGeneration(); + logger.info("Sleeping for " + StorageService.RING_DELAY + "ms to ensure " + endpoint + " does not change"); + try + { + Thread.sleep(StorageService.RING_DELAY); + } + catch (InterruptedException e) + { + throw new AssertionError(e); + } + // make sure it did not change + epState = endpointStateMap.get(endpoint); + if (epState.getHeartBeatState().getGeneration() != generation) + throw new RuntimeException("Endpoint " + endpoint + " generation changed while trying to remove it"); + epState.updateTimestamp(); // make sure we don't evict it too soon + epState.getHeartBeatState().forceNewerGenerationUnsafe(); + } + if (token == null) + token = StorageService.instance.getBootstrapToken(); + // do not pass go, do not collect 200 dollars, just gtfo + epState.addApplicationState(ApplicationState.STATUS, StorageService.instance.valueFactory.left(token, computeExpireTime())); + handleMajorStateChange(endpoint, epState); + try + { + Thread.sleep(intervalInMillis * 4); + } + catch (InterruptedException e) + { + throw new AssertionError(e); + } + logger.warn("Finished killing {}", endpoint); + } + public boolean isKnownEndpoint(InetAddress endpoint) { return endpointStateMap.containsKey(endpoint); diff --git a/src/java/org/apache/cassandra/gms/GossiperMBean.java b/src/java/org/apache/cassandra/gms/GossiperMBean.java index 62e77eadad..574f4b83eb 100644 --- a/src/java/org/apache/cassandra/gms/GossiperMBean.java +++ b/src/java/org/apache/cassandra/gms/GossiperMBean.java @@ -28,4 +28,6 @@ public interface GossiperMBean public int getCurrentGenerationNumber(String address) throws UnknownHostException; + public void unsafeAssassinateEndpoint(String address) throws UnknownHostException; + } \ No newline at end of file