diff --git a/doc/modules/cassandra/pages/managing/operating/onboarding-to-accord.adoc b/doc/modules/cassandra/pages/managing/operating/onboarding-to-accord.adoc index e9fe5e386f41..e105aeacdf9d 100644 --- a/doc/modules/cassandra/pages/managing/operating/onboarding-to-accord.adoc +++ b/doc/modules/cassandra/pages/managing/operating/onboarding-to-accord.adoc @@ -229,9 +229,9 @@ Marking ranges as migrating is a lightweight operation and does not trigger the repairs that will finish the migration. The range to mark migrating needs to be explicitly -provided otherwise the entire ring will be marked migrating for the -specified keyspace and tables. If the entire range is marked migrating it is -only necessary to invoke `begin-migration` on one node. +provided otherwise it will default to the primary range +of the node that `nodetool` is connecting to. +This is similar to running repair with the -pr flag. This is only needed if `accord.default++_++transactional++_++mode=explicit` is set in diff --git a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java index 7a954c17ef89..ffd1677722a5 100644 --- a/src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java +++ b/src/java/org/apache/cassandra/service/consensus/migration/ConsensusTableMigration.java @@ -201,8 +201,17 @@ public static void startMigrationToConsensusProtocol(@Nullable List keys IPartitioner partitioner = DatabaseDescriptor.getPartitioner(); Optional>> maybeParsedRanges = maybeRangesStr.map(rangesStr -> ImmutableList.copyOf(RepairOption.parseRanges(rangesStr, partitioner))); - Token minToken = partitioner.getMinimumToken(); - NormalizedRanges ranges = normalizedRanges(maybeParsedRanges.orElse(ImmutableList.of(new Range(minToken, minToken)))); + + NormalizedRanges ranges; + if (maybeParsedRanges.isPresent()) + ranges = normalizedRanges(maybeParsedRanges.get()); + else + { + List> defaultRanges = new ArrayList<>(); + for (String keyspaceName : keyspaceNames) + defaultRanges.addAll(StorageService.instance.getPrimaryRanges(keyspaceName)); + ranges = normalizedRanges(defaultRanges); + } ClusterMetadataService.instance().commit(new BeginConsensusMigrationForTableAndRange(ranges, tableIds)); } @@ -216,7 +225,7 @@ public static Integer finishMigrationToConsensusProtocol(@Nonnull String keyspac checkNotNull(target); ClusterMetadata cm = ClusterMetadata.current(); - Optional>> localKeyspaceRanges = Optional.of(ImmutableList.copyOf(StorageService.instance.getLocalReplicas(keyspace).onlyFull().ranges())); + Optional>> localKeyspaceRanges = Optional.of(ImmutableList.copyOf(StorageService.instance.getPrimaryRanges(keyspace))); List> ranges = maybeRangesToRanges(maybeRangesStr, localKeyspaceRanges); Map allTableMigrationStates = ClusterMetadata.current().consensusMigrationState.tableStates; List tableIds = keyspacesAndTablesToTableIds(cm, ImmutableList.of(keyspace), maybeTables, Optional.of(allTableMigrationStates::containsKey)); diff --git a/test/distributed/org/apache/cassandra/distributed/test/accord/AccordMigrationTest.java b/test/distributed/org/apache/cassandra/distributed/test/accord/AccordMigrationTest.java index 869fb3487b5e..2dd3016e71c4 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/accord/AccordMigrationTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/accord/AccordMigrationTest.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -91,6 +93,7 @@ import org.apache.cassandra.service.paxos.Commit.Proposal; import org.apache.cassandra.service.paxos.PaxosState; import org.apache.cassandra.tcm.ClusterMetadata; +import org.apache.cassandra.tcm.ClusterMetadataService; import org.apache.cassandra.tcm.Epoch; import org.apache.cassandra.transport.Dispatcher; import org.apache.cassandra.utils.ByteArrayUtil; @@ -569,6 +572,47 @@ public void testPaxosToAccordSerialRead() throws Exception }); } + @Test + public void testBeginMigrationTargetsOnlyLocalRanges() throws Exception + { + List ddls = Arrays.asList("DROP KEYSPACE IF EXISTS " + KEYSPACE + ';', + "CREATE KEYSPACE " + KEYSPACE + " WITH REPLICATION={'class':'SimpleStrategy', 'replication_factor': 2}", + "CREATE TABLE " + qualifiedRegularTableName + " (k int PRIMARY KEY, v int)"); + test(ddls, cluster -> { + cluster.schemaChange("ALTER TABLE " + qualifiedRegularTableName + " WITH " + transactionalMode.asCqlParam()); + cluster.get(1).nodetoolResult("consensus_admin", "begin-migration"); + + String keyspace = KEYSPACE; + String tableName = regularTableName; + cluster.get(1).runOnInstance(() -> { + ConsensusMigrationState state = ClusterMetadataService.instance().metadata().consensusMigrationState; + Collection> expectedMigratingRange = StorageService.instance.getPrimaryRanges(keyspace); + assertEquals(normalizedRanges(expectedMigratingRange), state.tableStates.get(Schema.instance.getTableMetadata(keyspace, tableName).id()).migratingRanges()); + }); + }); + } + + @Test + public void testFinishMigrationTargetsOnlyLocalRanges() throws Exception + { + List ddls = Arrays.asList("DROP KEYSPACE IF EXISTS " + KEYSPACE + ';', + "CREATE KEYSPACE " + KEYSPACE + " WITH REPLICATION={'class':'SimpleStrategy', 'replication_factor': 2}", + "CREATE TABLE " + qualifiedRegularTableName + " (k int PRIMARY KEY, v int)"); + test(ddls, cluster -> { + cluster.schemaChange("ALTER TABLE " + qualifiedRegularTableName + " WITH " + transactionalMode.asCqlParam()); + cluster.get(1).nodetoolResult("consensus_admin", "begin-migration"); + cluster.get(1).nodetoolResult("consensus_admin", "finish-migration"); + + String keyspace = KEYSPACE; + String tableName = regularTableName; + cluster.get(1).runOnInstance(() -> { + ConsensusMigrationState state = ClusterMetadataService.instance().metadata().consensusMigrationState; + Collection> expectedMigratingRange = StorageService.instance.getPrimaryRanges(keyspace); + assertEquals(normalizedRanges(expectedMigratingRange), state.tableStates.get(Schema.instance.getTableMetadata(keyspace, tableName).id()).migratedRanges); + }); + }); + } + private void assertTransactionalModes(String keyspace, String table, TransactionalMode mode, TransactionalMigrationFromMode migration) { forEach(() -> {