Skip to content

Commit 4b9b879

Browse files
CRZbulabulaJackieTien97
authored andcommitted
Bound Ratis reconfiguration retries and add region migration ITs (#17895)
1 parent 96e8cf1 commit 4b9b879

23 files changed

Lines changed: 679 additions & 33 deletions

File tree

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppCommonConfig.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,27 @@ public CommonConfig setDataRatisTriggerSnapshotThreshold(long threshold) {
387387
return this;
388388
}
389389

390+
@Override
391+
public CommonConfig setConfigNodeRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
392+
setProperty(
393+
"config_node_ratis_reconfiguration_max_retry_attempts", String.valueOf(maxRetryAttempts));
394+
return this;
395+
}
396+
397+
@Override
398+
public CommonConfig setSchemaRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
399+
setProperty(
400+
"schema_region_ratis_reconfiguration_max_retry_attempts", String.valueOf(maxRetryAttempts));
401+
return this;
402+
}
403+
404+
@Override
405+
public CommonConfig setDataRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
406+
setProperty(
407+
"data_region_ratis_reconfiguration_max_retry_attempts", String.valueOf(maxRetryAttempts));
408+
return this;
409+
}
410+
390411
@Override
391412
public CommonConfig setSeriesSlotNum(int seriesSlotNum) {
392413
setProperty("series_slot_num", String.valueOf(seriesSlotNum));

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppSharedCommonConfig.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,27 @@ public CommonConfig setDataRatisTriggerSnapshotThreshold(long threshold) {
389389
return this;
390390
}
391391

392+
@Override
393+
public CommonConfig setConfigNodeRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
394+
cnConfig.setConfigNodeRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
395+
dnConfig.setConfigNodeRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
396+
return this;
397+
}
398+
399+
@Override
400+
public CommonConfig setSchemaRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
401+
cnConfig.setSchemaRegionRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
402+
dnConfig.setSchemaRegionRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
403+
return this;
404+
}
405+
406+
@Override
407+
public CommonConfig setDataRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
408+
cnConfig.setDataRegionRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
409+
dnConfig.setDataRegionRatisReconfigurationMaxRetryAttempts(maxRetryAttempts);
410+
return this;
411+
}
412+
392413
@Override
393414
public CommonConfig setSeriesSlotNum(int seriesSlotNum) {
394415
cnConfig.setSeriesSlotNum(seriesSlotNum);

integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteCommonConfig.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,21 @@ public CommonConfig setDataRatisTriggerSnapshotThreshold(long threshold) {
274274
return this;
275275
}
276276

277+
@Override
278+
public CommonConfig setConfigNodeRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
279+
return this;
280+
}
281+
282+
@Override
283+
public CommonConfig setSchemaRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
284+
return this;
285+
}
286+
287+
@Override
288+
public CommonConfig setDataRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts) {
289+
return this;
290+
}
291+
277292
@Override
278293
public CommonConfig setSeriesSlotNum(int seriesSlotNum) {
279294
return this;

integration-test/src/main/java/org/apache/iotdb/itbase/env/CommonConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ CommonConfig setEnableAutoLeaderBalanceForIoTConsensus(
124124

125125
CommonConfig setDataRatisTriggerSnapshotThreshold(long threshold);
126126

127+
CommonConfig setConfigNodeRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts);
128+
129+
CommonConfig setSchemaRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts);
130+
131+
CommonConfig setDataRegionRatisReconfigurationMaxRetryAttempts(int maxRetryAttempts);
132+
127133
CommonConfig setSeriesSlotNum(int seriesSlotNum);
128134

129135
CommonConfig setDataPartitionAllocationStrategy(String dataPartitionAllocationStrategy);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.confignode.it.regionmigration;
21+
22+
import org.apache.iotdb.consensus.ConsensusFactory;
23+
import org.apache.iotdb.it.env.EnvFactory;
24+
25+
import org.junit.Before;
26+
27+
public class IoTDBRegionMigrateITFrameworkForRatis
28+
extends IoTDBRegionOperationReliabilityITFramework {
29+
30+
@Override
31+
@Before
32+
public void setUp() throws Exception {
33+
super.setUp();
34+
EnvFactory.getEnv()
35+
.getConfig()
36+
.getCommonConfig()
37+
.setDataRegionConsensusProtocolClass(ConsensusFactory.RATIS_CONSENSUS)
38+
.setConfigNodeRatisReconfigurationMaxRetryAttempts(10)
39+
.setDataRegionRatisReconfigurationMaxRetryAttempts(10)
40+
.setSchemaRegionRatisReconfigurationMaxRetryAttempts(10);
41+
}
42+
}

integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionOperationReliabilityITFramework.java

Lines changed: 110 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,28 @@ public void failTest(
176176
killNode);
177177
}
178178

179+
public void failAndRollbackTest(
180+
final int dataReplicateFactor,
181+
final int schemaReplicationFactor,
182+
final int configNodeNum,
183+
final int dataNodeNum,
184+
KeySetView<String, Boolean> killConfigNodeKeywords,
185+
KeySetView<String, Boolean> killDataNodeKeywords,
186+
KillNode killNode)
187+
throws Exception {
188+
generalTestWithAllOptions(
189+
dataReplicateFactor,
190+
schemaReplicationFactor,
191+
configNodeNum,
192+
dataNodeNum,
193+
killConfigNodeKeywords,
194+
killDataNodeKeywords,
195+
actionOfKillNode,
196+
false,
197+
killNode,
198+
true);
199+
}
200+
179201
public void killClusterTest(
180202
KeySetView<String, Boolean> configNodeKeywords, boolean expectMigrateSuccess)
181203
throws Exception {
@@ -204,6 +226,31 @@ public void generalTestWithAllOptions(
204226
final boolean expectMigrateSuccess,
205227
KillNode killNode)
206228
throws Exception {
229+
generalTestWithAllOptions(
230+
dataReplicateFactor,
231+
schemaReplicationFactor,
232+
configNodeNum,
233+
dataNodeNum,
234+
configNodeKeywords,
235+
dataNodeKeywords,
236+
actionWhenDetectKeyWords,
237+
expectMigrateSuccess,
238+
killNode,
239+
false);
240+
}
241+
242+
private void generalTestWithAllOptions(
243+
final int dataReplicateFactor,
244+
final int schemaReplicationFactor,
245+
final int configNodeNum,
246+
final int dataNodeNum,
247+
KeySetView<String, Boolean> configNodeKeywords,
248+
KeySetView<String, Boolean> dataNodeKeywords,
249+
Consumer<KillPointContext> actionWhenDetectKeyWords,
250+
final boolean expectMigrateSuccess,
251+
KillNode killNode,
252+
boolean expectRollbackWhenFail)
253+
throws Exception {
207254
// prepare env
208255
EnvFactory.getEnv()
209256
.getConfig()
@@ -266,26 +313,42 @@ public void generalTestWithAllOptions(
266313
statement.execute(buildRegionMigrateCommand(selectedRegion, originalDataNode, destDataNode));
267314

268315
boolean success = false;
269-
Predicate<TShowRegionResp> migrateRegionPredicate =
270-
tShowRegionResp -> {
271-
Map<Integer, Set<Integer>> newRegionMap =
272-
getRegionMap(tShowRegionResp.getRegionInfoList());
273-
Set<Integer> dataNodes = newRegionMap.get(selectedRegion);
274-
return !dataNodes.contains(originalDataNode) && dataNodes.contains(destDataNode);
275-
};
276-
try {
277-
awaitUntilSuccess(
278-
client,
279-
selectedRegion,
280-
migrateRegionPredicate,
281-
Optional.of(destDataNode),
282-
Optional.of(originalDataNode));
283-
success = true;
284-
} catch (ConditionTimeoutException e) {
285-
if (expectMigrateSuccess) {
286-
LOGGER.error("Region migrate failed", e);
316+
if (expectRollbackWhenFail) {
317+
awaitKillPointsTriggered(configNodeKeywords);
318+
awaitKillPointsTriggered(dataNodeKeywords);
319+
try {
320+
awaitUntilSuccess(
321+
client,
322+
selectedRegion,
323+
rollbackPredicate(selectedRegion, regionMap.get(selectedRegion), destDataNode),
324+
Optional.empty(),
325+
Optional.of(destDataNode));
326+
} catch (ConditionTimeoutException e) {
327+
LOGGER.error("Region migrate did not roll back", e);
287328
Assert.fail();
288329
}
330+
} else {
331+
Predicate<TShowRegionResp> migrateRegionPredicate =
332+
tShowRegionResp -> {
333+
Map<Integer, Set<Integer>> newRegionMap =
334+
getRegionMap(tShowRegionResp.getRegionInfoList());
335+
Set<Integer> dataNodes = newRegionMap.get(selectedRegion);
336+
return !dataNodes.contains(originalDataNode) && dataNodes.contains(destDataNode);
337+
};
338+
try {
339+
awaitUntilSuccess(
340+
client,
341+
selectedRegion,
342+
migrateRegionPredicate,
343+
Optional.of(destDataNode),
344+
Optional.of(originalDataNode));
345+
success = true;
346+
} catch (ConditionTimeoutException e) {
347+
if (expectMigrateSuccess) {
348+
LOGGER.error("Region migrate failed", e);
349+
Assert.fail();
350+
}
351+
}
289352
}
290353
if (!expectMigrateSuccess && success) {
291354
LOGGER.error("Region migrate succeeded unexpectedly");
@@ -311,6 +374,28 @@ public void generalTestWithAllOptions(
311374
}
312375
}
313376

377+
private static Predicate<TShowRegionResp> rollbackPredicate(
378+
int selectedRegion, Set<Integer> originalDataNodes, int destDataNode) {
379+
return tShowRegionResp -> {
380+
List<TRegionInfo> selectedDataRegionInfos =
381+
tShowRegionResp.getRegionInfoList().stream()
382+
.filter(
383+
regionInfo ->
384+
regionInfo.getConsensusGroupId().getType() == TConsensusGroupType.DataRegion
385+
&& regionInfo.getConsensusGroupId().getId() == selectedRegion)
386+
.collect(Collectors.toList());
387+
Set<Integer> dataNodes =
388+
selectedDataRegionInfos.stream()
389+
.map(TRegionInfo::getDataNodeId)
390+
.collect(Collectors.toSet());
391+
return dataNodes.equals(originalDataNodes)
392+
&& !dataNodes.contains(destDataNode)
393+
&& selectedDataRegionInfos.stream()
394+
.allMatch(
395+
regionInfo -> RegionStatus.Running.getStatus().equals(regionInfo.getStatus()));
396+
};
397+
}
398+
314399
public static Set<Integer> getAllDataNodes(Statement statement) throws Exception {
315400
ResultSet result = statement.executeQuery(SHOW_DATANODES);
316401
Set<Integer> allDataNodeId = new HashSet<>();
@@ -428,6 +513,13 @@ void checkKillPointsAllTriggered(KeySetView<String, Boolean> killPoints) {
428513
}
429514
}
430515

516+
private static void awaitKillPointsTriggered(KeySetView<String, Boolean> killPoints) {
517+
if (killPoints.isEmpty()) {
518+
return;
519+
}
520+
Awaitility.await().atMost(2, TimeUnit.MINUTES).until(killPoints::isEmpty);
521+
}
522+
431523
private static String buildRegionMigrateCommand(int who, int from, int to) {
432524
String result = String.format(REGION_MIGRATE_COMMAND_FORMAT, who, from, to);
433525
LOGGER.info(result);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.confignode.it.regionmigration.pass.daily.datanodecrash.ratis;
21+
22+
import org.apache.iotdb.commons.utils.KillPoint.DataNodeKillPoints;
23+
import org.apache.iotdb.commons.utils.KillPoint.KillNode;
24+
import org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateITFrameworkForRatis;
25+
import org.apache.iotdb.it.framework.IoTDBTestRunner;
26+
import org.apache.iotdb.itbase.category.DailyIT;
27+
28+
import org.junit.Test;
29+
import org.junit.experimental.categories.Category;
30+
import org.junit.runner.RunWith;
31+
32+
@Category({DailyIT.class})
33+
@RunWith(IoTDBTestRunner.class)
34+
public class IoTDBRegionMigrateAddingPeerCrashForRatisIT
35+
extends IoTDBRegionMigrateITFrameworkForRatis {
36+
37+
@Test
38+
public void addingPeerCrashShouldFailAndRollback() throws Exception {
39+
failAndRollbackTest(
40+
2,
41+
2,
42+
1,
43+
3,
44+
noKillPoints(),
45+
buildSet(DataNodeKillPoints.DESTINATION_CREATE_LOCAL_PEER),
46+
KillNode.DESTINATION_DATANODE);
47+
}
48+
}

0 commit comments

Comments
 (0)