From bf0f80cbb67b1fe6b190cdeeee135d0dc73c4e52 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 9 Dec 2011 18:14:14 +0000 Subject: [PATCH] Add jmx method to forcibly remove endpoints. Patch by brandonwilliams reviewed by Paul Cannon for CASSANDRA-3337. git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-1.0@1212556 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/cassandra/gms/Gossiper.java | 60 +++++++++++++++++++ .../apache/cassandra/gms/GossiperMBean.java | 2 + 2 files changed, 62 insertions(+) diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java index 92f61ff2737c..fea71b1a7311 100644 --- a/src/java/org/apache/cassandra/gms/Gossiper.java +++ b/src/java/org/apache/cassandra/gms/Gossiper.java @@ -432,6 +432,66 @@ public void advertiseTokenRemoved(InetAddress endpoint, Token token) } } + /** + * 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 62e77eadade8..574f4b83eb53 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