mirror of https://github.com/apache/cassandra
Port GossipTest::nodeDownDuringMove to 4.0
Patch by Sam Tunnicliffe; reviewed by Ekaterina Dimitrova for CASSANDRA-15148
This commit is contained in:
parent
d656f8ac01
commit
bf96367f4d
|
|
@ -690,6 +690,9 @@ public class Instance extends IsolatedExecutor implements IInvokableInstance
|
|||
@Override
|
||||
public Future<Void> shutdown(boolean graceful)
|
||||
{
|
||||
if (!graceful)
|
||||
MessagingService.instance().shutdown(1L, MINUTES, false, true);
|
||||
|
||||
Future<?> future = async((ExecutorService executor) -> {
|
||||
Throwable error = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,17 @@
|
|||
package org.apache.cassandra.distributed.test;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
|
@ -35,15 +39,98 @@ import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
|||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import org.apache.cassandra.dht.Token;
|
||||
import org.apache.cassandra.distributed.Cluster;
|
||||
import org.apache.cassandra.gms.ApplicationState;
|
||||
import org.apache.cassandra.gms.EndpointState;
|
||||
import org.apache.cassandra.gms.Gossiper;
|
||||
import org.apache.cassandra.locator.InetAddressAndPort;
|
||||
import org.apache.cassandra.service.StorageService;
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static org.apache.cassandra.distributed.api.Feature.GOSSIP;
|
||||
import static org.apache.cassandra.distributed.api.Feature.NETWORK;
|
||||
import static org.apache.cassandra.distributed.impl.DistributedTestSnitch.toCassandraInetAddressAndPort;
|
||||
|
||||
public class GossipTest extends TestBaseImpl
|
||||
{
|
||||
@Test
|
||||
public void nodeDownDuringMove() throws Throwable
|
||||
{
|
||||
int liveCount = 1;
|
||||
try (Cluster cluster = Cluster.build(2 + liveCount)
|
||||
.withConfig(config -> config.with(NETWORK).with(GOSSIP))
|
||||
.createWithoutStarting())
|
||||
{
|
||||
int fail = liveCount + 1;
|
||||
int late = fail + 1;
|
||||
for (int i = 1 ; i <= liveCount ; ++i)
|
||||
cluster.get(i).startup();
|
||||
cluster.get(fail).startup();
|
||||
Collection<String> expectTokens =
|
||||
cluster.get(fail)
|
||||
.callsOnInstance(() -> StorageService.instance.getTokenMetadata()
|
||||
.getTokens(FBUtilities.getBroadcastAddressAndPort())
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList()))
|
||||
.call();
|
||||
|
||||
InetSocketAddress failAddress = cluster.get(fail).broadcastAddress();
|
||||
// wait for NORMAL state
|
||||
for (int i = 1 ; i <= liveCount ; ++i)
|
||||
{
|
||||
cluster.get(i).acceptsOnInstance((InetSocketAddress address) -> {
|
||||
EndpointState ep;
|
||||
InetAddressAndPort endpoint = toCassandraInetAddressAndPort(address);
|
||||
while (null == (ep = Gossiper.instance.getEndpointStateForEndpoint(endpoint))
|
||||
|| ep.getApplicationState(ApplicationState.STATUS_WITH_PORT) == null
|
||||
|| !ep.getApplicationState(ApplicationState.STATUS_WITH_PORT).value.startsWith("NORMAL"))
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10L));
|
||||
}).accept(failAddress);
|
||||
}
|
||||
|
||||
// set ourselves to MOVING, and wait for it to propagate
|
||||
cluster.get(fail).runOnInstance(() -> {
|
||||
Token token = Iterables.getFirst(StorageService.instance.getTokenMetadata().getTokens(FBUtilities.getBroadcastAddressAndPort()), null);
|
||||
Gossiper.instance.addLocalApplicationState(ApplicationState.STATUS_WITH_PORT, StorageService.instance.valueFactory.moving(token));
|
||||
});
|
||||
for (int i = 1 ; i <= liveCount ; ++i)
|
||||
{
|
||||
cluster.get(i).acceptsOnInstance((InetSocketAddress address) -> {
|
||||
EndpointState ep;
|
||||
InetAddressAndPort endpoint = toCassandraInetAddressAndPort(address);
|
||||
while (null == (ep = Gossiper.instance.getEndpointStateForEndpoint(endpoint))
|
||||
|| (ep.getApplicationState(ApplicationState.STATUS_WITH_PORT) == null
|
||||
|| !ep.getApplicationState(ApplicationState.STATUS_WITH_PORT).value.startsWith("MOVING")))
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
|
||||
}).accept(failAddress);
|
||||
}
|
||||
|
||||
cluster.get(fail).shutdown(false).get();
|
||||
cluster.get(late).startup();
|
||||
cluster.get(late).acceptsOnInstance((InetSocketAddress address) -> {
|
||||
EndpointState ep;
|
||||
InetAddressAndPort endpoint = toCassandraInetAddressAndPort(address);
|
||||
while (null == (ep = Gossiper.instance.getEndpointStateForEndpoint(endpoint))
|
||||
|| !ep.getApplicationState(ApplicationState.STATUS_WITH_PORT).value.startsWith("MOVING"))
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
|
||||
}).accept(failAddress);
|
||||
|
||||
Collection<String> tokens =
|
||||
cluster.get(late)
|
||||
.appliesOnInstance((InetSocketAddress address) ->
|
||||
StorageService.instance.getTokenMetadata()
|
||||
.getTokens(toCassandraInetAddressAndPort(address))
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList()))
|
||||
.apply(failAddress);
|
||||
|
||||
Assert.assertEquals(expectTokens, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BBBootstrapInterceptor
|
||||
{
|
||||
final static CountDownLatch bootstrapReady = new CountDownLatch(1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue