diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBMigrateMultiRegionForIoTV1IT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBMigrateMultiRegionForIoTV1IT.java index 102de89ccf7f8..8a5246a004e7c 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBMigrateMultiRegionForIoTV1IT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBMigrateMultiRegionForIoTV1IT.java @@ -37,6 +37,7 @@ import java.sql.Connection; import java.sql.Statement; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -51,6 +52,7 @@ @RunWith(IoTDBTestRunner.class) public class IoTDBMigrateMultiRegionForIoTV1IT extends IoTDBRegionOperationReliabilityITFramework { private static final String MULTI_REGION_MIGRATE_FORMAT = "migrate region %s from %d to %d"; + private static final String EXPAND_FORMAT = "extend region %d to %d"; private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBMigrateMultiRegionForIoTV1IT.class); @@ -83,6 +85,10 @@ public void multiRegionMigrateTest() throws Exception { Map> regionMap = getAllRegionMap(statement); Set allDataNodeId = getAllDataNodes(statement); + // INSERTION1 only creates one schema region and one data region; with replication factor 1 + // they are often placed on different DataNodes. Colocate them before multi-region migrate. + regionMap = ensureDataNodeHostsMultipleRegions(statement, client, regionMap); + // With replication factor 1 every region lives on exactly one DataNode. Pick a source // DataNode that hosts at least two regions, then migrate all its regions to a fresh // destination DataNode. @@ -170,6 +176,71 @@ public void multiRegionMigrateTest() throws Exception { } } + private Map> ensureDataNodeHostsMultipleRegions( + Statement statement, + SyncConfigNodeIServiceClient client, + Map> regionMap) + throws Exception { + if (hasDataNodeHostingMultipleRegions(regionMap)) { + return regionMap; + } + List regionIds = new ArrayList<>(regionMap.keySet()); + Assert.assertTrue("Need at least two regions to colocate", regionIds.size() >= 2); + + int firstRegion = regionIds.get(0); + int secondRegion = regionIds.get(1); + int targetDataNode = regionMap.get(secondRegion).iterator().next(); + if (regionMap.get(firstRegion).contains(targetDataNode)) { + targetDataNode = regionMap.get(firstRegion).iterator().next(); + regionGroupExpand(statement, client, secondRegion, targetDataNode); + } else { + regionGroupExpand(statement, client, firstRegion, targetDataNode); + } + return getAllRegionMap(statement); + } + + private boolean hasDataNodeHostingMultipleRegions(Map> regionMap) { + return regionMap.values().stream() + .flatMap(Set::stream) + .collect(Collectors.groupingBy(dataNodeId -> dataNodeId, Collectors.counting())) + .values() + .stream() + .anyMatch(count -> count >= 2); + } + + private void regionGroupExpand( + Statement statement, + SyncConfigNodeIServiceClient client, + int selectedRegion, + int targetDataNode) + throws Exception { + Awaitility.await() + .atMost(10, TimeUnit.SECONDS) + .pollInterval(1, TimeUnit.SECONDS) + .until( + () -> { + statement.execute(String.format(EXPAND_FORMAT, selectedRegion, targetDataNode)); + return true; + }); + + Predicate expandRegionPredicate = + tShowRegionResp -> { + Map> newRegionMap = + getRunningRegionMap(tShowRegionResp.getRegionInfoList()); + Set dataNodes = newRegionMap.get(selectedRegion); + return dataNodes != null && dataNodes.contains(targetDataNode); + }; + + awaitUntilSuccess( + client, + selectedRegion, + expandRegionPredicate, + Optional.of(targetDataNode), + Optional.empty()); + + LOGGER.info("Region {} has expanded to DataNode {}", selectedRegion, targetDataNode); + } + private int selectDataNodeHostingMultipleRegions(Map> regionMap) { Map regionCountPerDataNode = regionMap.values().stream() diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java similarity index 93% rename from integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java rename to integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java index eabb11b3155ce..d5c3a1b9c476c 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirIT.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1; +package org.apache.iotdb.confignode.it.regionmigration.pass.commit; import org.apache.iotdb.consensus.ConsensusFactory; import org.apache.iotdb.it.env.EnvFactory; @@ -43,12 +43,12 @@ import static org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionOperationReliabilityITFramework.getAllDataNodes; import static org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionOperationReliabilityITFramework.getDataRegionMapWithLeader; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.MULTI_DATA_DIRS; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitModsVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitRegionReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitTsFileResourceVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitTsFileVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.getReplicaDataNodeIds; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.MULTI_DATA_DIRS; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitModsVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitRegionReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitTsFileResourceVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitTsFileVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.getReplicaDataNodeIds; /** * Tree-model coverage for IoTConsensus region migration over multiple data dirs: a deletion (mods) diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java similarity index 93% rename from integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java rename to integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java index ee71d48fc66b4..8407d37d0f598 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionMigrateWithDeletionMultiDataDirTableIT.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1; +package org.apache.iotdb.confignode.it.regionmigration.pass.commit; import org.apache.iotdb.consensus.ConsensusFactory; import org.apache.iotdb.isession.SessionConfig; @@ -45,12 +45,12 @@ import static org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionOperationReliabilityITFramework.getAllDataNodes; import static org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionOperationReliabilityITFramework.getDataRegionMapWithLeader; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.MULTI_DATA_DIRS; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitModsVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitRegionReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitTsFileResourceVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.awaitTsFileVisibleOnReplicas; -import static org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1.RegionMigrateFileAssertions.getReplicaDataNodeIds; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.MULTI_DATA_DIRS; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitModsVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitRegionReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitTsFileResourceVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.awaitTsFileVisibleOnReplicas; +import static org.apache.iotdb.confignode.it.regionmigration.pass.commit.RegionMigrateFileAssertions.getReplicaDataNodeIds; /** * Table-model twin of {@link IoTDBRegionMigrateWithDeletionMultiDataDirIT}: a deletion (mods) must diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/RegionMigrateFileAssertions.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/RegionMigrateFileAssertions.java similarity index 98% rename from integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/RegionMigrateFileAssertions.java rename to integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/RegionMigrateFileAssertions.java index 1cdf5981d3450..0dff2731f42d2 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/RegionMigrateFileAssertions.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/RegionMigrateFileAssertions.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.confignode.it.regionmigration.pass.daily.iotv1; +package org.apache.iotdb.confignode.it.regionmigration.pass.commit; import org.apache.iotdb.it.env.EnvFactory; import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;