This is an automated email from the ASF dual-hosted git repository. samt pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 7b89979dc8488c4348101f88687f48a56a05781b Author: Sam Tunnicliffe <s...@apache.org> AuthorDate: Mon Apr 29 09:16:33 2024 +0100 When repairing system_cluster_metadata always repair full range Patch by Sam Tunnicliffe; reviewed by Marcus Eriksson for CASSANDRA-19709 --- CHANGES.txt | 1 + .../cassandra/repair/messages/RepairOption.java | 5 ++- .../distributed/test/RepairOperationalTest.java | 50 ++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 862df73c83..221fde20cf 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 5.1 + * Always repair the full range when repairing system_cluster_metadata (CASSANDRA-19709) * Use table-specific partitioners during Paxos repair (CASSANDRA-19714) * Expose current compaction throughput in nodetool (CASSANDRA-13890) * CEP-24 Password validation / generation (CASSANDRA-17457) diff --git a/src/java/org/apache/cassandra/repair/messages/RepairOption.java b/src/java/org/apache/cassandra/repair/messages/RepairOption.java index f0508a3e42..03097da077 100644 --- a/src/java/org/apache/cassandra/repair/messages/RepairOption.java +++ b/src/java/org/apache/cassandra/repair/messages/RepairOption.java @@ -28,6 +28,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Token; +import org.apache.cassandra.locator.MetaStrategy; import org.apache.cassandra.streaming.PreviewKind; import org.apache.cassandra.repair.RepairParallelism; @@ -202,7 +203,9 @@ public class RepairOption } // ranges - Set<Range<Token>> ranges = parseRanges(options.get(RANGES_KEY), partitioner); + Set<Range<Token>> ranges = partitioner == MetaStrategy.partitioner + ? Collections.singleton(MetaStrategy.entireRange) + : parseRanges(options.get(RANGES_KEY), partitioner); boolean asymmetricSyncing = Boolean.parseBoolean(options.get(OPTIMISE_STREAMS_KEY)); diff --git a/test/distributed/org/apache/cassandra/distributed/test/RepairOperationalTest.java b/test/distributed/org/apache/cassandra/distributed/test/RepairOperationalTest.java index a4628db32e..9eccb45ac6 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/RepairOperationalTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/RepairOperationalTest.java @@ -30,11 +30,14 @@ import org.apache.cassandra.db.compaction.CompactionManager; import org.apache.cassandra.distributed.Cluster; import org.apache.cassandra.distributed.api.ConsistencyLevel; import org.apache.cassandra.distributed.api.IInvokableInstance; +import org.apache.cassandra.locator.MetaStrategy; import org.assertj.core.api.Assertions; import static net.bytebuddy.matcher.ElementMatchers.named; import static org.apache.cassandra.distributed.api.Feature.GOSSIP; import static org.apache.cassandra.distributed.api.Feature.NETWORK; +import static org.apache.cassandra.schema.SchemaConstants.METADATA_KEYSPACE_NAME; +import static org.junit.Assert.assertEquals; public class RepairOperationalTest extends TestBaseImpl { @@ -211,4 +214,51 @@ public class RepairOperationalTest extends TestBaseImpl } } + @Test + public void repairClusterMetadataKeyspaceAlwaysUsesFullRange() throws IOException + { + try (Cluster cluster = init(Cluster.build(2) + .withConfig(config -> config.with(GOSSIP).with(NETWORK)) + .start())) + { + cluster.get(1).nodetoolResult("cms", "reconfigure", "2").asserts().success(); + cluster.schemaChange(withKeyspace("create table %s.tbl (id int primary key)")); + for (int i = 0; i < 5; i++) + { + for (int j = 0; j < 5; j++) + { + cluster.schemaChange(withKeyspace(String.format("alter table %%s.tbl with comment = 'comment " + i + j + "'", i, j))); + } + cluster.forEach(inst -> inst.flush(METADATA_KEYSPACE_NAME)); + } + + IInvokableInstance node = cluster.get(1); + // run repairs with a very small range and check that the entire range is what actually gets repaired + // incremental first + node.nodetoolResult("repair", "-st", "1", "-et", "2", METADATA_KEYSPACE_NAME).asserts().success(); + assertAllRepairsOnEntireRange(node, 1); + // now a full repair + node.nodetoolResult("repair", "-full", "-st", "1", "-et", "2", METADATA_KEYSPACE_NAME).asserts().success(); + assertAllRepairsOnEntireRange(node, 2); + } + } + + private void assertAllRepairsOnEntireRange(IInvokableInstance node, int expectedRepairs) + { + // check that the range was expanded to cover the entire range + Object[][] rows = node.executeInternal("SELECT range_begin, range_end " + + "FROM system_distributed.repair_history " + + "WHERE keyspace_name = ? ALLOW FILTERING", + METADATA_KEYSPACE_NAME); + assertEquals(expectedRepairs, rows.length); + for (Object[] row : rows) + { + String st = (String) row[0]; + String et = (String) row[1]; + assertEquals(Long.parseLong(st), MetaStrategy.partitioner.getMinimumToken().getLongValue()); + assertEquals(Long.parseLong(et), MetaStrategy.partitioner.getMinimumToken().getLongValue()); + } + } + + } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org