use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class IPMembershipTest method startupNewIP.
/**
* Tests the behavior if a node restarts with a different IP.
*/
@Test
public void startupNewIP() throws IOException, InterruptedException {
try (Cluster cluster = Cluster.build(3).withConfig(c -> c.with(Feature.GOSSIP, Feature.NATIVE_PROTOCOL).set("endpoint_snitch", "org.apache.cassandra.locator.SimpleSnitch")).start()) {
IInvokableInstance nodeToReplace = cluster.get(3);
ToolRunner.invokeCassandraStress("write", "n=10000", "-schema", "replication(factor=3)", "-port", "native=9042").assertOnExitCode();
stopUnchecked(nodeToReplace);
// change the IP of the node
updateAddress(nodeToReplace, "127.0.0.4");
nodeToReplace.startup();
// gossip takes some time, wait for the other nodes to see this one updated
ClusterUtils.awaitRingJoin(cluster.get(1), "127.0.0.4");
ClusterUtils.awaitRingJoin(cluster.get(2), "127.0.0.4");
Set<String> expected = ImmutableSet.of("127.0.0.1", "127.0.0.2", "127.0.0.4");
cluster.forEach(i -> assertRingIs(i, expected));
ToolRunner.invokeCassandraStress("read", "n=10000", "no-warmup", "-port", "native=9042").assertOnExitCode();
}
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class AbstractNetstatsBootstrapStreaming method executeTest.
protected void executeTest(final boolean streamEntireSSTables, final boolean compressionEnabled, final int throughput) throws Exception {
final Cluster.Builder builder = builder().withNodes(1).withTokenSupplier(TokenSupplier.evenlyDistributedTokens(2)).withNodeIdTopology(NetworkTopology.singleDcNetworkTopology(2, "dc0", "rack0")).withConfig(config -> config.with(NETWORK, GOSSIP, NATIVE_PROTOCOL).set(streamEntireSSTables ? "entire_sstable_stream_throughput_outbound" : "stream_throughput_outbound", throughput + "MiB/s").set("compaction_throughput", "1MiB/s").set("stream_entire_sstables", streamEntireSSTables));
try (final Cluster cluster = builder.withNodes(1).start()) {
// populate data only against 1 node first
createTable(cluster, 1, compressionEnabled);
cluster.get(1).nodetoolResult("disableautocompaction", "netstats_test").asserts().success();
populateData(compressionEnabled);
cluster.get(1).flush("netstats_test");
// then bootstrap the second one, upon joining,
// we should see that netstats shows how SSTables are being streamed on the first node
final IInstanceConfig config = cluster.newInstanceConfig();
config.set("auto_bootstrap", true);
IInvokableInstance secondNode = cluster.bootstrap(config);
final Future<?> startupRunnable = executorService.submit((Runnable) secondNode::startup);
final Future<AbstractNetstatsStreaming.NetstatResults> netstatsFuture = executorService.submit(new NetstatsCallable(cluster.get(1)));
startupRunnable.get(3, MINUTES);
// 1m is a bit much, but should be fine on slower environments. Node2 can't come up without streaming
// completing, so if node2 is up 1m is enough time for the nodetool watcher to yield
final AbstractNetstatsStreaming.NetstatResults results = netstatsFuture.get(1, MINUTES);
results.assertSuccessful();
AbstractNetstatsStreaming.NetstatsOutputParser.validate(AbstractNetstatsStreaming.NetstatsOutputParser.parse(results));
}
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class SimulatedAction method applyToMessage.
Action applyToMessage(IInvokableInstance from, IInvokableInstance to, IMessage message) {
Executor executor = to.executorFor(message.verb());
if (executor instanceof ImmediateExecutor)
executor = to.executor();
InterceptedExecution.InterceptedTaskExecution task = new InterceptedRunnableExecution((InterceptingExecutor) executor, () -> to.receiveMessageWithInvokingThread(message));
Verb verb = Verb.fromId(message.verb());
Modifiers self = verbModifiers.getOrDefault(verb, NONE);
int fromNum = from.config().num();
int toNum = to.config().num();
Deliver deliver;
if (is(Modifier.RELIABLE) || self.is(Modifier.RELIABLE))
deliver = DELIVER;
else
deliver = simulated.futureScheduler.shouldDeliver(fromNum, toNum);
Action action;
switch(deliver) {
default:
throw new AssertionError();
case DELIVER:
{
Object description = lazy(() -> String.format("%s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), message.from(), to.broadcastAddress()));
OrderOn orderOn = task.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, verb, task);
action.setDeadline(simulated.futureScheduler.messageDeadlineNanos(fromNum, toNum));
break;
}
case FAILURE:
case TIMEOUT:
{
task.cancel();
self = DROP.with(self);
InetSocketAddress failedOn;
IInvokableInstance notify;
if (verb.isResponse()) {
failedOn = from.broadcastAddress();
notify = to;
} else {
failedOn = to.broadcastAddress();
notify = from;
}
InterceptedExecution.InterceptedTaskExecution failTask = new InterceptedRunnableExecution((InterceptingExecutor) notify.executorFor(verb.id), () -> notify.unsafeApplyOnThisThread((socketAddress, id, isTimeout) -> {
InetAddressAndPort address = InetAddressAndPort.getByAddress(socketAddress);
RequestCallbacks.CallbackInfo callback = instance().callbacks.remove(id, address);
if (callback != null) {
RequestCallback<?> invokeOn = (RequestCallback<?>) callback.callback;
RequestFailureReason reason = isTimeout ? RequestFailureReason.TIMEOUT : RequestFailureReason.UNKNOWN;
invokeOn.onFailure(address, reason);
}
return null;
}, failedOn, message.id(), deliver == TIMEOUT));
Object description = (lazy(() -> String.format("Report Timeout of %s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), failedOn, notify.broadcastAddress())));
OrderOn orderOn = failTask.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, failTask);
switch(deliver) {
default:
throw new AssertionError();
case TIMEOUT:
long expiresAfterNanos = from.unsafeApplyOnThisThread(id -> Verb.fromId(id).expiresAfterNanos(), (verb.isResponse() ? forVerb : verb).id);
action.setDeadline(simulated.futureScheduler.messageTimeoutNanos(expiresAfterNanos));
break;
case FAILURE:
action.setDeadline(simulated.futureScheduler.messageFailureNanos(toNum, fromNum));
break;
}
break;
}
}
return action;
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class ForceRepairTest method force.
private void force(boolean includeDifference) throws IOException {
long nowInMicro = System.currentTimeMillis() * 1000;
try (Cluster cluster = Cluster.build(3).withConfig(c -> c.set("hinted_handoff_enabled", false).with(Feature.values())).start()) {
init(cluster);
cluster.schemaChange(withKeyspace("CREATE TABLE %s.tbl (k INT PRIMARY KEY, v INT)"));
for (int i = 0; i < 10; i++) cluster.coordinator(1).execute(withKeyspace("INSERT INTO %s.tbl (k,v) VALUES (?, ?) USING TIMESTAMP ?"), ConsistencyLevel.ALL, i, i, nowInMicro++);
ClusterUtils.stopUnchecked(cluster.get(2));
// repair should fail because node2 is down
IInvokableInstance node1 = cluster.get(1);
for (String[] args : Arrays.asList(new String[] { "--full" }, new String[] { "--full", "--preview" }, // nothing should be in the repaired set, so shouldn't stream
new String[] { "--full", "--validate" }, // IR Preview
new String[] { "--preview" }, // nothing should be in the repaired set, so shouldn't stream
new String[] { "--validate" }, // IR
new String[0])) {
if (includeDifference)
// each loop should have a different timestamp, causing a new difference
node1.executeInternal(withKeyspace("INSERT INTO %s.tbl (k,v) VALUES (?, ?) USING TIMESTAMP ?"), -1, -1, nowInMicro++);
try {
node1.nodetoolResult(ArrayUtils.addAll(new String[] { "repair", KEYSPACE }, args)).asserts().failure();
node1.nodetoolResult(ArrayUtils.addAll(new String[] { "repair", KEYSPACE, "--force" }, args)).asserts().success();
assertNoRepairedAt(cluster);
} catch (Exception | Error e) {
// tag the error to include which args broke
e.addSuppressed(new AssertionError("Failure for args: " + Arrays.toString(args)));
throw e;
}
}
if (includeDifference) {
SimpleQueryResult expected = QueryResults.builder().row(-1, -1).build();
for (IInvokableInstance node : Arrays.asList(node1, cluster.get(3))) {
SimpleQueryResult results = node.executeInternalWithResult(withKeyspace("SELECT * FROM %s.tbl WHERE k=?"), -1);
expected.reset();
AssertUtils.assertRows(results, expected);
}
}
}
}
use of org.apache.cassandra.distributed.api.IInvokableInstance in project cassandra by apache.
the class UpgradeSSTablesTest method rewriteSSTablesTest.
@Test
public void rewriteSSTablesTest() throws Throwable {
try (ICluster<IInvokableInstance> cluster = builder().withNodes(1).withDataDirCount(1).start()) {
for (String compressionBefore : new String[] { "{'class' : 'LZ4Compressor', 'chunk_length_in_kb' : 32}", "{'enabled': 'false'}" }) {
for (String command : new String[] { "upgradesstables", "recompress_sstables" }) {
cluster.schemaChange(withKeyspace("DROP KEYSPACE IF EXISTS %s"));
cluster.schemaChange(withKeyspace("CREATE KEYSPACE %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};"));
cluster.schemaChange(withKeyspace("CREATE TABLE %s.tbl (pk int, ck int, v text, PRIMARY KEY (pk, ck)) " + "WITH compression = " + compressionBefore));
cluster.get(1).acceptsOnInstance((String ks) -> {
Keyspace.open(ks).getColumnFamilyStore("tbl").disableAutoCompaction();
}).accept(KEYSPACE);
String blob = "blob";
for (int i = 0; i < 6; i++) blob += blob;
for (int i = 0; i < 100; i++) {
cluster.coordinator(1).execute(withKeyspace("INSERT INTO %s.tbl (pk, ck, v) VALUES (?,?,?)"), ConsistencyLevel.QUORUM, i, i, blob);
}
cluster.get(1).nodetool("flush", KEYSPACE, "tbl");
Assert.assertEquals(0, cluster.get(1).nodetool("upgradesstables", "-a", KEYSPACE, "tbl"));
cluster.schemaChange(withKeyspace("ALTER TABLE %s.tbl WITH compression = {'class' : 'LZ4Compressor', 'chunk_length_in_kb' : 128};"));
// Make sure timestamp will be different even with 1-second resolution.
Thread.sleep(2000);
long maxSoFar = cluster.get(1).appliesOnInstance((String ks) -> {
long maxTs = -1;
ColumnFamilyStore cfs = Keyspace.open(ks).getColumnFamilyStore("tbl");
cfs.disableAutoCompaction();
for (SSTableReader tbl : cfs.getLiveSSTables()) {
maxTs = Math.max(maxTs, tbl.getCreationTimeFor(Component.DATA));
}
return maxTs;
}).apply(KEYSPACE);
for (int i = 100; i < 200; i++) {
cluster.coordinator(1).execute(withKeyspace("INSERT INTO %s.tbl (pk, ck, v) VALUES (?,?,?)"), ConsistencyLevel.QUORUM, i, i, blob);
}
cluster.get(1).nodetool("flush", KEYSPACE, "tbl");
LogAction logAction = cluster.get(1).logs();
logAction.mark();
long expectedCount = cluster.get(1).appliesOnInstance((String ks, Long maxTs) -> {
long count = 0;
long skipped = 0;
Set<SSTableReader> liveSSTables = Keyspace.open(ks).getColumnFamilyStore("tbl").getLiveSSTables();
assert liveSSTables.size() == 2 : String.format("Expected 2 sstables, but got " + liveSSTables.size());
for (SSTableReader tbl : liveSSTables) {
if (tbl.getCreationTimeFor(Component.DATA) <= maxTs)
count++;
else
skipped++;
}
assert skipped > 0;
return count;
}).apply(KEYSPACE, maxSoFar);
if (command.equals("upgradesstables"))
Assert.assertEquals(0, cluster.get(1).nodetool("upgradesstables", "-a", "-t", Long.toString(maxSoFar), KEYSPACE, "tbl"));
else
Assert.assertEquals(0, cluster.get(1).nodetool("recompress_sstables", KEYSPACE, "tbl"));
Assert.assertFalse(logAction.grep(String.format("%d sstables to", expectedCount)).getResult().isEmpty());
}
}
}
}
Aggregations