use of org.apache.cassandra.distributed.Cluster in project cassandra by apache.
the class PreviewRepairTest method testFinishingIncRepairDuringPreview.
/**
* another case where the repaired datasets could mismatch is if an incremental repair finishes just as the preview
* repair is starting up.
*
* This tests this case:
* 1. we start a preview repair
* 2. pause the validation requests from node1 -> node2
* 3. node1 starts its validation
* 4. run an incremental repair which completes fine
* 5. node2 resumes its validation
*
* Now we will include sstables from the second incremental repair on node2 but not on node1
* This should fail since we fail any preview repair which is ongoing when an incremental repair finishes (step 4 above)
*/
@Test
public void testFinishingIncRepairDuringPreview() throws IOException, InterruptedException, ExecutionException {
ExecutorService es = Executors.newSingleThreadExecutor();
try (Cluster cluster = init(Cluster.build(2).withConfig(config -> config.with(GOSSIP).with(NETWORK)).start())) {
cluster.schemaChange("create table " + KEYSPACE + ".tbl (id int primary key, t int)");
insert(cluster.coordinator(1), 0, 100);
cluster.forEach((node) -> node.flush(KEYSPACE));
cluster.get(1).callOnInstance(repair(options(false, false)));
insert(cluster.coordinator(1), 100, 100);
cluster.forEach((node) -> node.flush(KEYSPACE));
Condition previewRepairStarted = newOneTimeCondition();
Condition continuePreviewRepair = newOneTimeCondition();
DelayFirstRepairTypeMessageFilter filter = validationRequest(previewRepairStarted, continuePreviewRepair);
// this pauses the validation request sent from node1 to node2 until we have run a full inc repair below
cluster.filters().outbound().verbs(VALIDATION_REQ.id).from(1).to(2).messagesMatching(filter).drop();
Future<RepairResult> rsFuture = es.submit(() -> cluster.get(1).callOnInstance(repair(options(true, false))));
previewRepairStarted.await();
// this needs to finish before the preview repair is unpaused on node2
cluster.get(1).callOnInstance(repair(options(false, false)));
continuePreviewRepair.signalAll();
RepairResult rs = rsFuture.get();
// preview repair should have failed
assertFalse(rs.success);
// and no mismatches should have been reported
assertFalse(rs.wasInconsistent);
} finally {
es.shutdown();
}
}
use of org.apache.cassandra.distributed.Cluster in project cassandra by apache.
the class ReadDigestConsistencyTest method testDigestConsistency.
@Test
public void testDigestConsistency() throws Exception {
try (Cluster cluster = init(builder().withNodes(2).start())) {
cluster.schemaChange(CREATE_TABLE);
insertData(cluster.coordinator(1));
testDigestConsistency(cluster.coordinator(1));
testDigestConsistency(cluster.coordinator(2));
}
}
use of org.apache.cassandra.distributed.Cluster in project cassandra by apache.
the class ReadRepairTest method testRangeSliceQueryWithTombstones.
/**
* Verify that range queries with CL>ONE don't do unnecessary read-repairs when there are tombstones.
* <p>
* See CASSANDRA-8989 and CASSANDRA-9502.
* <p>
* Migrated from Python dtest read_repair_test.py:TestReadRepair.test_range_slice_query_with_tombstones()
*/
private void testRangeSliceQueryWithTombstones(boolean flush) throws Throwable {
try (Cluster cluster = init(Cluster.create(2))) {
cluster.schemaChange(withKeyspace("CREATE TABLE %s.t (k int, c int, v int, PRIMARY KEY(k, c))"));
ICoordinator coordinator = cluster.coordinator(1);
// insert some rows in all nodes
String insertQuery = withKeyspace("INSERT INTO %s.t (k, c, v) VALUES (?, ?, ?)");
for (int k = 0; k < 10; k++) {
for (int c = 0; c < 10; c++) coordinator.execute(insertQuery, ALL, k, c, k * c);
}
// delete a subset of the inserted partitions, plus some others that don't exist
String deletePartitionQuery = withKeyspace("DELETE FROM %s.t WHERE k = ?");
for (int k = 5; k < 15; k++) {
coordinator.execute(deletePartitionQuery, ALL, k);
}
// delete some of the rows of some of the partitions, including deleted and not deleted partitions
String deleteRowQuery = withKeyspace("DELETE FROM %s.t WHERE k = ? AND c = ?");
for (int k = 2; k < 7; k++) {
for (int c = 0; c < 5; c++) coordinator.execute(deleteRowQuery, ALL, k, c);
}
// delete some of the rows of some not-existent partitions, including deleted and never-written partitions
for (int k = 12; k < 17; k++) {
for (int c = 0; c < 5; c++) coordinator.execute(deleteRowQuery, ALL, k, c);
}
// flush all the nodes if specified
if (flush) {
for (int n = 1; n <= cluster.size(); n++) cluster.get(n).flush(KEYSPACE);
}
// run a bunch of queries verifying that they don't trigger read repair
coordinator.execute(withKeyspace("SELECT * FROM %s.t LIMIT 100"), QUORUM);
for (int k = 0; k < 15; k++) {
coordinator.execute(withKeyspace("SELECT * FROM %s.t WHERE k=?"), QUORUM, k);
for (int c = 0; c < 10; c++) {
coordinator.execute(withKeyspace("SELECT * FROM %s.t WHERE k=? AND c=?"), QUORUM, k, c);
coordinator.execute(withKeyspace("SELECT * FROM %s.t WHERE k=? AND c>?"), QUORUM, k, c);
coordinator.execute(withKeyspace("SELECT * FROM %s.t WHERE k=? AND c<?"), QUORUM, k, c);
}
}
long requests = ReadRepairTester.readRepairRequestsCount(cluster.get(1), "t");
assertEquals("No read repair requests were expected, found " + requests, 0, requests);
}
}
use of org.apache.cassandra.distributed.Cluster in project cassandra by apache.
the class ReadRepairTest method alterRFAndRunReadRepair.
/**
* Test that there is no read repair with RF=1, and that altering it to RF>1 doesn't trigger any repair by
* itself but following queries will use read repair accordingly with the new RF.
*/
@Test
public void alterRFAndRunReadRepair() throws Throwable {
try (Cluster cluster = builder().withNodes(2).start()) {
cluster.schemaChange(withKeyspace("CREATE KEYSPACE %s WITH replication = " + "{'class': 'SimpleStrategy', 'replication_factor': 1}"));
cluster.schemaChange(withKeyspace("CREATE TABLE %s.t (k int PRIMARY KEY, a int, b int)" + " WITH read_repair='blocking'"));
// insert a row that will only get to one node due to the RF=1
Object[] row = row(1, 1, 1);
cluster.get(1).executeInternal(withKeyspace("INSERT INTO %s.t (k, a, b) VALUES (?, ?, ?)"), row);
// flush to ensure reads come from sstables
cluster.get(1).flush(KEYSPACE);
// at RF=1 it shouldn't matter which node we query, as the data should always come from the only replica
String query = withKeyspace("SELECT * FROM %s.t WHERE k = 1");
for (int i = 1; i <= cluster.size(); i++) assertRows(cluster.coordinator(i).execute(query, ALL), row);
// at RF=1 the prevoius queries shouldn't have triggered read repair
assertRows(cluster.get(1).executeInternal(query), row);
assertRows(cluster.get(2).executeInternal(query));
// alter RF
System.setProperty(Config.PROPERTY_PREFIX + "allow_alter_rf_during_range_movement", "true");
cluster.schemaChange(withKeyspace("ALTER KEYSPACE %s WITH replication = " + "{'class': 'SimpleStrategy', 'replication_factor': 2}"));
// altering the RF shouldn't have triggered any read repair
assertRows(cluster.get(1).executeInternal(query), row);
assertRows(cluster.get(2).executeInternal(query));
// query again at CL=ALL, this time the data should be repaired
assertRows(cluster.coordinator(2).execute(query, ALL), row);
assertRows(cluster.get(1).executeInternal(query), row);
assertRows(cluster.get(2).executeInternal(query), row);
}
}
use of org.apache.cassandra.distributed.Cluster in project cassandra by apache.
the class ReadRepairTest method movingTokenReadRepairTest.
@Test
public void movingTokenReadRepairTest() throws Throwable {
try (Cluster cluster = init(Cluster.create(4), 3)) {
List<Token> tokens = cluster.tokens();
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v int, PRIMARY KEY (pk, ck)) WITH read_repair='blocking'");
int i = 0;
while (true) {
Token t = Murmur3Partitioner.instance.getToken(Int32Type.instance.decompose(i));
// the list of tokens uses zero-based numbering, whereas the cluster nodes use one-based numbering
if (t.compareTo(tokens.get(2 - 1)) < 0 && t.compareTo(tokens.get(1 - 1)) > 0)
break;
++i;
}
// write only to #4
cluster.get(4).executeInternal("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v) VALUES (?, 1, 1)", i);
// mark #2 as leaving in #4
cluster.get(4).acceptsOnInstance((InetSocketAddress endpoint) -> {
StorageService.instance.getTokenMetadata().addLeavingEndpoint(InetAddressAndPort.getByAddressOverrideDefaults(endpoint.getAddress(), endpoint.getPort()));
PendingRangeCalculatorService.instance.update();
PendingRangeCalculatorService.instance.blockUntilFinished();
}).accept(cluster.get(2).broadcastAddress());
// prevent #4 from reading or writing to #3, so our QUORUM must contain #2 and #4
// since #1 is taking over the range, this means any read-repair must make it to #1 as well
// (as a speculative repair in this case, as we prefer to send repair mutations to the initial
// set of read replicas, which are 2 and 3 here).
cluster.filters().verbs(READ_REQ.id).from(4).to(3).drop();
cluster.filters().verbs(READ_REPAIR_REQ.id).from(4).to(3).drop();
assertRows(cluster.coordinator(4).execute("SELECT * FROM " + KEYSPACE + ".tbl WHERE pk = ?", ConsistencyLevel.QUORUM, i), row(i, 1, 1));
// verify that #1 receives the write
assertRows(cluster.get(1).executeInternal("SELECT * FROM " + KEYSPACE + ".tbl WHERE pk = ?", i), row(i, 1, 1));
}
}
Aggregations