/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cassandra.gms; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import org.junit.BeforeClass; import org.junit.Test; import org.apache.cassandra.Util; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.RandomPartitioner; import org.apache.cassandra.dht.Token; import org.apache.cassandra.locator.TokenMetadata; import org.apache.cassandra.service.StorageService; import static org.junit.Assert.assertFalse; public class FailureDetectorTest { @BeforeClass public static void setup() { // slow unit tests can cause problems with FailureDetector's GC pause handling System.setProperty("cassandra.max_local_pause_in_ms", "20000"); DatabaseDescriptor.daemonInitialization(); } @Test public void testConvictAfterLeft() throws UnknownHostException { StorageService ss = StorageService.instance; TokenMetadata tmd = ss.getTokenMetadata(); tmd.clearUnsafe(); IPartitioner partitioner = new RandomPartitioner(); VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner); ArrayList<Token> endpointTokens = new ArrayList<>(); ArrayList<Token> keyTokens = new ArrayList<>(); List<InetAddress> hosts = new ArrayList<>(); List<UUID> hostIds = new ArrayList<>(); // we want to convict if there is any heartbeat data present in the FD DatabaseDescriptor.setPhiConvictThreshold(0); // create a ring of 2 nodes Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 3); InetAddress leftHost = hosts.get(1); FailureDetector.instance.report(leftHost); // trigger handleStateLeft in StorageService ss.onChange(leftHost, ApplicationState.STATUS, valueFactory.left(Collections.singleton(endpointTokens.get(1)), Gossiper.computeExpireTime())); // confirm that handleStateLeft was called and leftEndpoint was removed from TokenMetadata assertFalse("Left endpoint not removed from TokenMetadata", tmd.isMember(leftHost)); // confirm the FD's history for leftHost didn't get wiped by status jump to LEFT FailureDetector.instance.interpret(leftHost); assertFalse("Left endpoint not convicted", FailureDetector.instance.isAlive(leftHost)); } }