use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class HostReplacementTest method seedGoesDownBeforeDownHost.
/**
* If the seed goes down, then another node, once the seed comes back, make sure host replacements still work.
*/
@Test
public void seedGoesDownBeforeDownHost() throws IOException {
// start with 3 nodes, stop both nodes, start the seed, host replace the down node)
TokenSupplier even = TokenSupplier.evenlyDistributedTokens(3);
try (Cluster cluster = Cluster.build(3).withConfig(c -> c.with(Feature.GOSSIP, Feature.NETWORK)).withTokenSupplier(node -> even.token(node == 4 ? 2 : node)).start()) {
// call early as this can't be touched on a down node
IInvokableInstance seed = cluster.get(1);
IInvokableInstance nodeToRemove = cluster.get(2);
IInvokableInstance nodeToStayAlive = cluster.get(3);
setupCluster(cluster);
// collect rows/tokens to detect issues later on if the state doesn't match
SimpleQueryResult expectedState = nodeToRemove.coordinator().executeWithResult("SELECT * FROM " + KEYSPACE + ".tbl", ConsistencyLevel.ALL);
List<String> beforeCrashTokens = getTokenMetadataTokens(seed);
// shutdown the seed, then the node to remove
stopUnchecked(seed);
stopUnchecked(nodeToRemove);
// restart the seed
seed.startup();
// make sure the node to remove is still in the ring
assertInRing(seed, nodeToRemove);
// make sure node1 still has node2's tokens
List<String> currentTokens = getTokenMetadataTokens(seed);
Assertions.assertThat(currentTokens).as("Tokens no longer match after restarting").isEqualTo(beforeCrashTokens);
// now create a new node to replace the other node
IInvokableInstance replacingNode = replaceHostAndStart(cluster, nodeToRemove);
List<IInvokableInstance> expectedRing = Arrays.asList(seed, replacingNode, nodeToStayAlive);
// wait till the replacing node is in the ring
awaitRingJoin(seed, replacingNode);
awaitRingJoin(replacingNode, seed);
awaitRingJoin(nodeToStayAlive, replacingNode);
// make sure all nodes are healthy
logger.info("Current ring is {}", awaitRingHealthy(seed));
expectedRing.forEach(i -> assertRingIs(i, expectedRing));
validateRows(seed.coordinator(), expectedState);
validateRows(replacingNode.coordinator(), expectedState);
}
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class SnapshotsTest method testSnapshotInvalidArgument.
@Test
public void testSnapshotInvalidArgument() throws Exception {
IInvokableInstance instance = cluster.get(1);
instance.nodetoolResult("snapshot", "--ttl", String.format("%ds", 1), "-t", "basic").asserts().failure().stdoutContains(String.format("ttl for snapshot must be at least %d seconds", FIVE_SECONDS));
instance.nodetoolResult("snapshot", "--ttl", "invalid-ttl").asserts().failure();
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class UnableToParseClientMessageTest method test.
private void test(String expectedError, Message.Request request, Predicate<List<String>> shouldCheckLogs) throws IOException {
// write gibberish to the native protocol
IInvokableInstance node = CLUSTER.get(1);
// maintance note: this error isn't required to be consistent cross release, so if this changes its ok to update the test to reflect the new exception.
long currentCount = getProtocolExceptionCount(node);
long logStart = node.logs().mark();
try (SimpleClient client = SimpleClient.builder("127.0.0.1", 9042).protocolVersion(version).useBeta().build()) {
client.connect(false, true);
// this should return a failed response
// in pre-v5 the connection isn't closed, so use `false` to avoid waiting
Message.Response response = client.execute(request, false);
Assert.assertEquals(Message.Type.ERROR, response.type);
Assert.assertTrue(response.toString(), response.toString().contains(expectedError));
node.runOnInstance(() -> {
// channelRead throws then channelInactive throws after trying to read remaining bytes
// using spinAssertEquals as the metric is updated AFTER replying back to the client
// so there is a race where we check the metric before it gets updated
Util.spinAssertEquals(currentCount + 1L, () -> CassandraMetricsRegistry.Metrics.getMeters().get("org.apache.cassandra.metrics.Client.ProtocolException").getCount(), 10);
Assert.assertEquals(0, CassandraMetricsRegistry.Metrics.getMeters().get("org.apache.cassandra.metrics.Client.UnknownException").getCount());
});
// the logs are noSpamLogger, so each iteration may not produce a new log; only valid if present and not seen before
List<String> results = node.logs().grep(logStart, "Protocol exception with client networking").getResult();
if (shouldCheckLogs.test(results)) {
Assertions.assertThat(results).isNotEmpty();
results.forEach(s -> Assertions.assertThat(s).contains(expectedError));
}
}
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class StreamCloseInMiddleTest method assertNoNodeShutdown.
private void assertNoNodeShutdown(Cluster cluster) {
AssertionError t = null;
for (IInvokableInstance i : cluster.stream().collect(Collectors.toList())) {
try {
Assertions.assertThat(i.isShutdown()).describedAs("%s was shutdown; this is not expected", i).isFalse();
Assertions.assertThat(i.killAttempts()).describedAs("%s saw kill attempts; this is not expected", i).isEqualTo(0);
} catch (AssertionError t2) {
if (t == null)
t = t2;
else
t.addSuppressed(t2);
}
}
if (t != null)
throw t;
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class ReprepareTestOldBehaviour method testReprepareMixedVersionWithoutReset.
@Test
public void testReprepareMixedVersionWithoutReset() throws Throwable {
try (ICluster<IInvokableInstance> c = init(builder().withNodes(2).withConfig(config -> config.with(GOSSIP, NETWORK, NATIVE_PROTOCOL)).withInstanceInitializer(PrepareBehaviour::oldBehaviour).start())) {
ForceHostLoadBalancingPolicy lbp = new ForceHostLoadBalancingPolicy();
c.schemaChange(withKeyspace("CREATE TABLE %s.tbl (pk int, ck int, v int, PRIMARY KEY (pk, ck));"));
// 1 has old behaviour
for (int firstContact : new int[] { 1, 2 }) {
for (boolean withUse : new boolean[] { true, false }) {
for (boolean clearBetweenExecutions : new boolean[] { true, false }) {
try (com.datastax.driver.core.Cluster cluster = com.datastax.driver.core.Cluster.builder().addContactPoint("127.0.0.1").addContactPoint("127.0.0.2").withLoadBalancingPolicy(lbp).build();
Session session = cluster.connect()) {
if (withUse)
session.execute(withKeyspace("USE %s"));
lbp.setPrimary(firstContact);
final PreparedStatement select = session.prepare(withKeyspace("SELECT * FROM %s.tbl"));
session.execute(select.bind());
if (clearBetweenExecutions)
c.get(2).runOnInstance(QueryProcessor::clearPreparedStatementsCache);
lbp.setPrimary(firstContact == 1 ? 2 : 1);
session.execute(select.bind());
if (clearBetweenExecutions)
c.get(2).runOnInstance(QueryProcessor::clearPreparedStatementsCache);
lbp.setPrimary(firstContact);
session.execute(select.bind());
c.get(2).runOnInstance(QueryProcessor::clearPreparedStatementsCache);
}
}
}
}
}
}
Aggregations