From 97609fd4c5dd5d227bc0ea2d676e4e22a7dd13e2 Mon Sep 17 00:00:00 2001 From: Xiangpeng Hu <65238551+HxpSerein@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:02:48 +0800 Subject: [PATCH] resolve conflicts --- .../IoTDBRemoveDataNodeITFramework.java | 76 ++++++++++++++----- .../IoTDBRemoveDataNodeNormalIT.java | 15 +++- .../it/removedatanode/SQLModel.java | 26 +++++++ .../iotdb/db/qp/sql/IdentifierParser.g4 | 1 + .../apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 7 +- .../org/apache/iotdb/db/qp/sql/SqlLexer.g4 | 4 + .../execution/config/ConfigTaskVisitor.java | 8 ++ .../executor/ClusterConfigTaskExecutor.java | 71 +++++++++++++++++ .../config/executor/IConfigTaskExecutor.java | 3 + .../config/metadata/RemoveDataNodeTask.java | 43 +++++++++++ .../queryengine/plan/parser/ASTVisitor.java | 12 +++ .../plan/statement/StatementVisitor.java | 5 ++ .../metadata/RemoveDataNodeStatement.java | 74 ++++++++++++++++++ .../region/ExtendRegionStatement.java | 14 ++++ .../region/MigrateRegionStatement.java | 14 ++++ .../region/ReconstructRegionStatement.java | 14 ++++ .../region/RemoveRegionStatement.java | 14 ++++ 17 files changed, 378 insertions(+), 23 deletions(-) create mode 100644 integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/SQLModel.java create mode 100644 iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/RemoveDataNodeTask.java create mode 100644 iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/RemoveDataNodeStatement.java diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeITFramework.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeITFramework.java index f01ee42ab2a1..73d5fd6fac35 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeITFramework.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeITFramework.java @@ -29,6 +29,7 @@ import org.apache.iotdb.it.env.EnvFactory; import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper; import org.apache.iotdb.itbase.exception.InconsistentDataException; +import org.apache.iotdb.jdbc.IoTDBSQLException; import org.apache.iotdb.rpc.TSStatusCode; import org.apache.thrift.TException; @@ -57,7 +58,7 @@ public class IoTDBRemoveDataNodeITFramework { private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBRemoveDataNodeITFramework.class); - private static final String INSERTION1 = + private static final String TREE_MODEL_INSERTION = "INSERT INTO root.sg.d1(timestamp,speed,temperature) values(100, 1, 2)"; private static final String SHOW_REGIONS = "show regions"; @@ -90,7 +91,8 @@ public void successTest( final int dataNodeNum, final int removeDataNodeNum, final int dataRegionPerDataNode, - final boolean rejoinRemovedDataNode) + final boolean rejoinRemovedDataNode, + final SQLModel model) throws Exception { testRemoveDataNode( dataReplicateFactor, @@ -100,7 +102,8 @@ public void successTest( removeDataNodeNum, dataRegionPerDataNode, true, - rejoinRemovedDataNode); + rejoinRemovedDataNode, + model); } public void failTest( @@ -110,7 +113,8 @@ public void failTest( final int dataNodeNum, final int removeDataNodeNum, final int dataRegionPerDataNode, - final boolean rejoinRemovedDataNode) + final boolean rejoinRemovedDataNode, + final SQLModel model) throws Exception { testRemoveDataNode( dataReplicateFactor, @@ -120,7 +124,8 @@ public void failTest( removeDataNodeNum, dataRegionPerDataNode, false, - rejoinRemovedDataNode); + rejoinRemovedDataNode, + model); } public void testRemoveDataNode( @@ -131,7 +136,8 @@ public void testRemoveDataNode( final int removeDataNodeNum, final int dataRegionPerDataNode, final boolean expectRemoveSuccess, - final boolean rejoinRemovedDataNode) + final boolean rejoinRemovedDataNode, + final SQLModel model) throws Exception { // Set up the environment EnvFactory.getEnv() @@ -148,8 +154,8 @@ public void testRemoveDataNode( SyncConfigNodeIServiceClient client = (SyncConfigNodeIServiceClient) EnvFactory.getEnv().getLeaderConfigNodeConnection()) { - // Insert data - statement.execute(INSERTION1); + // Insert data in tree model + statement.execute(TREE_MODEL_INSERTION); Map> regionMap = getDataRegionMap(statement); regionMap.forEach( @@ -187,21 +193,39 @@ public void testRemoveDataNode( .map(TDataNodeConfiguration::getLocation) .filter(location -> removeDataNodes.contains(location.getDataNodeId())) .collect(Collectors.toList()); - TDataNodeRemoveReq removeReq = new TDataNodeRemoveReq(removeDataNodeLocations); + if (SQLModel.NOT_USE_SQL.equals(model)) { + TDataNodeRemoveReq removeReq = new TDataNodeRemoveReq(removeDataNodeLocations); + + // Remove data nodes + TDataNodeRemoveResp removeResp = clientRef.get().removeDataNode(removeReq); + LOGGER.info("Submit Remove DataNodes result {} ", removeResp); + if (removeResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + if (expectRemoveSuccess) { + LOGGER.error("Submit Remove DataNodes fail"); + Assert.fail(); + } else { + LOGGER.info("Submit Remove DataNodes fail, as expected."); + return; + } + } + LOGGER.info("Submit Remove DataNodes request: {}", removeReq); - // Remove data nodes - TDataNodeRemoveResp removeResp = clientRef.get().removeDataNode(removeReq); - LOGGER.info("Submit Remove DataNodes result {} ", removeResp); - if (removeResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { - if (expectRemoveSuccess) { - LOGGER.error("Submit Remove DataNodes fail"); - Assert.fail(); - } else { - LOGGER.info("Submit Remove DataNodes fail, as expected"); - return; + } else { + String removeDataNodeSQL = generateRemoveString(removeDataNodes); + LOGGER.info("Remove DataNodes SQL: {}", removeDataNodeSQL); + try { + statement.execute(removeDataNodeSQL); + } catch (IoTDBSQLException e) { + if (expectRemoveSuccess) { + LOGGER.error("Remove DataNodes SQL execute fail: {}", e.getMessage()); + Assert.fail(); + } else { + LOGGER.info("Submit Remove DataNodes fail, as expected"); + return; + } } + LOGGER.info("Remove DataNodes SQL submit successfully."); } - LOGGER.info("Submit Remove DataNodes request: {}", removeReq); // Wait until success boolean removeSuccess = false; @@ -363,4 +387,16 @@ public void restartDataNodes(List dataNodeWrappers) { LOGGER.info("Node {} restarted.", nodeWrapper.getId()); }); } + + public static String generateRemoveString(Set dataNodes) { + StringBuilder sb = new StringBuilder("remove datanode "); + + for (Integer node : dataNodes) { + sb.append(node).append(", "); + } + + sb.setLength(sb.length() - 2); + + return sb.toString(); + } } diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeNormalIT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeNormalIT.java index f091499bf02f..517d8ee4cad6 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeNormalIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/IoTDBRemoveDataNodeNormalIT.java @@ -29,13 +29,24 @@ @Category({ClusterIT.class}) @RunWith(IoTDBTestRunner.class) public class IoTDBRemoveDataNodeNormalIT extends IoTDBRemoveDataNodeITFramework { + @Test public void success1C4DTest() throws Exception { - successTest(2, 3, 1, 4, 1, 2, true); + successTest(2, 3, 1, 4, 1, 2, true, SQLModel.NOT_USE_SQL); } @Test public void fail1C3DTest() throws Exception { - failTest(2, 3, 1, 3, 1, 2, false); + failTest(2, 3, 1, 3, 1, 2, false, SQLModel.NOT_USE_SQL); + } + + @Test + public void success1C4DTestUseSQL() throws Exception { + successTest(2, 3, 1, 4, 1, 2, true, SQLModel.TREE_MODEL_SQL); + } + + @Test + public void fail1C3DTestUseSQL() throws Exception { + failTest(2, 3, 1, 3, 1, 2, false, SQLModel.TREE_MODEL_SQL); } } diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/SQLModel.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/SQLModel.java new file mode 100644 index 000000000000..0963072d44ca --- /dev/null +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/removedatanode/SQLModel.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.confignode.it.removedatanode; + +public enum SQLModel { + NOT_USE_SQL, + + TREE_MODEL_SQL, +} diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 index fac1ad4b46e5..b1a785a8ef8b 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 @@ -78,6 +78,7 @@ keyWords | DATA_REGION_GROUP_NUM | DATABASE | DATABASES + | DATANODE | DATANODEID | DATANODES | DATASET diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 index 596336e133ae..64136c76493a 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 @@ -65,7 +65,7 @@ ddlStatement // Cluster | showVariables | showCluster | showRegions | showDataNodes | showConfigNodes | showClusterId | getRegionId | getTimeSlotList | countTimeSlotList | getSeriesSlotList - | migrateRegion | reconstructRegion | extendRegion | removeRegion + | migrateRegion | reconstructRegion | extendRegion | removeRegion | removeDataNode | verifyConnection // AINode | showAINodes | createModel | dropModel | showModels | callInference @@ -554,6 +554,11 @@ verifyConnection : VERIFY CONNECTION (DETAILS)? ; +// ---- Remove DataNode +removeDataNode + : REMOVE DATANODE dataNodeId=INTEGER_LITERAL (COMMA dataNodeId=INTEGER_LITERAL)* + ; + // Pipe Task ========================================================================================= createPipe : CREATE PIPE (IF NOT EXISTS)? pipeName=identifier diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 index d6ea1be56ed5..556dfebb48b0 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 @@ -217,6 +217,10 @@ DATABASES : D A T A B A S E S ; +DATANODE + : D A T A N O D E + ; + DATANODEID : D A T A N O D E I D ; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/ConfigTaskVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/ConfigTaskVisitor.java index 5231b3c7a2d6..347f44c2fe05 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/ConfigTaskVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/ConfigTaskVisitor.java @@ -37,6 +37,7 @@ import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.GetRegionIdTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.GetSeriesSlotListTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.GetTimeSlotListTask; +import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.RemoveDataNodeTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.SetTTLTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowClusterDetailsTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowClusterIdTask; @@ -114,6 +115,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatement; @@ -607,6 +609,12 @@ public IConfigTask visitRemoveRegion( return new RemoveRegionTask(removeRegionStatement); } + @Override + public IConfigTask visitRemoveDataNode( + RemoveDataNodeStatement removeDataNodeStatement, MPPQueryContext context) { + return new RemoveDataNodeTask(removeDataNodeStatement); + } + @Override public IConfigTask visitCreateContinuousQuery( CreateContinuousQueryStatement createContinuousQueryStatement, MPPQueryContext context) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java index 1b4e25cca733..7402a9b99e24 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java @@ -19,6 +19,8 @@ package org.apache.iotdb.db.queryengine.plan.execution.config.executor; +import org.apache.iotdb.common.rpc.thrift.TDataNodeConfiguration; +import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation; import org.apache.iotdb.common.rpc.thrift.TFlushReq; import org.apache.iotdb.common.rpc.thrift.TSStatus; import org.apache.iotdb.common.rpc.thrift.TSetConfigurationReq; @@ -69,6 +71,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TCreatePipeReq; import org.apache.iotdb.confignode.rpc.thrift.TCreateTopicReq; import org.apache.iotdb.confignode.rpc.thrift.TCreateTriggerReq; +import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveReq; +import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveResp; import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema; import org.apache.iotdb.confignode.rpc.thrift.TDeactivateSchemaTemplateReq; import org.apache.iotdb.confignode.rpc.thrift.TDeleteDatabasesReq; @@ -184,6 +188,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDataNodesStatement; @@ -272,8 +277,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; @@ -2664,6 +2671,70 @@ public SettableFuture migrateRegion( return future; } + @Override + public SettableFuture removeDataNode( + final RemoveDataNodeStatement removeDataNodeStatement) { + final SettableFuture future = SettableFuture.create(); + try (ConfigNodeClient configNodeClient = + CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) { + Set nodeIds = removeDataNodeStatement.getNodeIds(); + + Set validNodeIds = + configNodeClient.getDataNodeConfiguration(-1).getDataNodeConfigurationMap().keySet(); + + Set invalidNodeIds = new HashSet<>(nodeIds); + invalidNodeIds.removeAll(validNodeIds); + + if (!invalidNodeIds.isEmpty()) { + LOGGER.info("Cannot remove invalid nodeIds:{}", invalidNodeIds); + nodeIds.removeAll(invalidNodeIds); + } + + LOGGER.info("Starting to remove DataNode with nodeIds: {}", nodeIds); + + final Set finalNodeIds = nodeIds; + List removeDataNodeLocations = + configNodeClient + .getDataNodeConfiguration(-1) + .getDataNodeConfigurationMap() + .values() + .stream() + .map(TDataNodeConfiguration::getLocation) + .filter(location -> finalNodeIds.contains(location.getDataNodeId())) + .collect(Collectors.toList()); + + List simplifiedLocations = new ArrayList<>(); + for (TDataNodeLocation dataNodeLocation : removeDataNodeLocations) { + simplifiedLocations.add( + dataNodeLocation.getDataNodeId() + + "@" + + dataNodeLocation.getInternalEndPoint().getIp()); + } + + LOGGER.info("Start to remove datanode, removed DataNodes endpoint: {}", simplifiedLocations); + TDataNodeRemoveReq removeReq = new TDataNodeRemoveReq(removeDataNodeLocations); + TDataNodeRemoveResp removeResp = configNodeClient.removeDataNode(removeReq); + LOGGER.info("Submit Remove DataNodes result {} ", removeResp); + if (removeResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + future.setException( + new IoTDBException( + removeResp.getStatus().toString(), removeResp.getStatus().getCode())); + return future; + } else { + LOGGER.info( + "Submit remove-datanode request successfully, but the process may fail. " + + "more details are shown in the logs of confignode-leader and removed-datanode, " + + "and after the process of removing datanode ends successfully, " + + "you are supposed to delete directory and data of the removed-datanode manually"); + future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS)); + } + } catch (Exception e) { + future.setException(e); + } + + return future; + } + @Override public SettableFuture reconstructRegion( ReconstructRegionStatement reconstructRegionStatement) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java index 18c91386ae3d..ce6f8868e6c1 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java @@ -39,6 +39,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDataNodesStatement; @@ -233,6 +234,8 @@ SettableFuture reconstructRegion( SettableFuture removeRegion(RemoveRegionStatement removeRegionStatement); + SettableFuture removeDataNode(RemoveDataNodeStatement removeDataNodeStatement); + SettableFuture createContinuousQuery( CreateContinuousQueryStatement createContinuousQueryStatement, MPPQueryContext context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/RemoveDataNodeTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/RemoveDataNodeTask.java new file mode 100644 index 000000000000..5a91da21f628 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/RemoveDataNodeTask.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.queryengine.plan.execution.config.metadata; + +import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult; +import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask; +import org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; + +import com.google.common.util.concurrent.ListenableFuture; + +public class RemoveDataNodeTask implements IConfigTask { + + protected final RemoveDataNodeStatement statement; + + public RemoveDataNodeTask(RemoveDataNodeStatement removeDataNodeStatement) { + this.statement = removeDataNodeStatement; + } + + @Override + public ListenableFuture execute(IConfigTaskExecutor configTaskExecutor) { + // If the action is executed successfully, return the Future. + // If your operation is async, you can return the corresponding future directly. + return configTaskExecutor.removeDataNode(statement); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java index 8330eca95b2a..f3643e4436b6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java @@ -148,6 +148,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildNodesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildPathsStatement; @@ -231,6 +232,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.io.BaseEncoding; import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; import org.apache.tsfile.common.conf.TSFileDescriptor; import org.apache.tsfile.common.constant.TsFileConstant; @@ -4170,6 +4172,16 @@ public Statement visitRemoveRegion(IoTDBSqlParser.RemoveRegionContext ctx) { Integer.parseInt(ctx.regionId.getText()), Integer.parseInt(ctx.targetDataNodeId.getText())); } + @Override + public Statement visitRemoveDataNode(IoTDBSqlParser.RemoveDataNodeContext ctx) { + List dataNodeIDs = + ctx.INTEGER_LITERAL().stream() + .map(ParseTree::getText) + .map(Integer::parseInt) + .collect(Collectors.toList()); + return new RemoveDataNodeStatement(dataNodeIDs); + } + @Override public Statement visitVerifyConnection(IoTDBSqlParser.VerifyConnectionContext ctx) { return new TestConnectionStatement(ctx.DETAILS() != null); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java index 7f4181be8b35..333d21aeccd4 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java @@ -55,6 +55,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetRegionIdStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetSeriesSlotListStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.GetTimeSlotListStatement; +import org.apache.iotdb.db.queryengine.plan.statement.metadata.RemoveDataNodeStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.SetTTLStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildNodesStatement; import org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowChildPathsStatement; @@ -593,6 +594,10 @@ public R visitRemoveRegion(RemoveRegionStatement removeRegionStatement, C contex return visitStatement(removeRegionStatement, context); } + public R visitRemoveDataNode(RemoveDataNodeStatement removeDataNodeStatement, C context) { + return visitStatement(removeDataNodeStatement, context); + } + public R visitDeactivateTemplate( DeactivateTemplateStatement deactivateTemplateStatement, C context) { return visitStatement(deactivateTemplateStatement, context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/RemoveDataNodeStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/RemoveDataNodeStatement.java new file mode 100644 index 000000000000..45fa94822288 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/RemoveDataNodeStatement.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.queryengine.plan.statement.metadata; + +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; +import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.auth.AuthorityChecker; +import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; +import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; +import org.apache.iotdb.db.queryengine.plan.statement.Statement; +import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; +import org.apache.iotdb.rpc.TSStatusCode; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class RemoveDataNodeStatement extends Statement implements IConfigStatement { + + final Set nodeIds; + + public RemoveDataNodeStatement(List dataNodeIDs) { + super(); + this.nodeIds = new HashSet<>(dataNodeIDs); + } + + public Set getNodeIds() { + return nodeIds; + } + + @Override + public TSStatus checkPermissionBeforeProcess(String userName) { + if (AuthorityChecker.SUPER_USER.equals(userName)) { + return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()); + } + return AuthorityChecker.getTSStatus( + AuthorityChecker.checkSystemPermission(userName, PrivilegeType.MAINTAIN.ordinal()), + PrivilegeType.MAINTAIN); + } + + @Override + public R accept(StatementVisitor visitor, C context) { + return visitor.visitRemoveDataNode(this, context); + } + + @Override + public QueryType getQueryType() { + return QueryType.WRITE; + } + + @Override + public List getPaths() { + return Collections.emptyList(); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ExtendRegionStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ExtendRegionStatement.java index 581ba6bf10fe..560adee4e9ef 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ExtendRegionStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ExtendRegionStatement.java @@ -19,11 +19,15 @@ package org.apache.iotdb.db.queryengine.plan.statement.metadata.region; +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; +import org.apache.iotdb.rpc.TSStatusCode; import java.util.Collections; import java.util.List; @@ -47,6 +51,16 @@ public int getDataNodeId() { return dataNodeId; } + @Override + public TSStatus checkPermissionBeforeProcess(String userName) { + if (AuthorityChecker.SUPER_USER.equals(userName)) { + return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()); + } + return AuthorityChecker.getTSStatus( + AuthorityChecker.checkSystemPermission(userName, PrivilegeType.MAINTAIN.ordinal()), + PrivilegeType.MAINTAIN); + } + @Override public R accept(StatementVisitor visitor, C context) { return visitor.visitExtendRegion(this, context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/MigrateRegionStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/MigrateRegionStatement.java index 616357f53795..5b290a533096 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/MigrateRegionStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/MigrateRegionStatement.java @@ -19,11 +19,15 @@ package org.apache.iotdb.db.queryengine.plan.statement.metadata.region; +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; +import org.apache.iotdb.rpc.TSStatusCode; import java.util.Collections; import java.util.List; @@ -63,6 +67,16 @@ public int getToId() { return toId; } + @Override + public TSStatus checkPermissionBeforeProcess(String userName) { + if (AuthorityChecker.SUPER_USER.equals(userName)) { + return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()); + } + return AuthorityChecker.getTSStatus( + AuthorityChecker.checkSystemPermission(userName, PrivilegeType.MAINTAIN.ordinal()), + PrivilegeType.MAINTAIN); + } + @Override public R accept(StatementVisitor visitor, C context) { return visitor.visitMigrateRegion(this, context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ReconstructRegionStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ReconstructRegionStatement.java index cd22e61ad7f7..7307381bf4e4 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ReconstructRegionStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/ReconstructRegionStatement.java @@ -19,11 +19,15 @@ package org.apache.iotdb.db.queryengine.plan.statement.metadata.region; +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; +import org.apache.iotdb.rpc.TSStatusCode; import java.util.Collections; import java.util.List; @@ -45,6 +49,16 @@ public List getRegionIds() { return regionIds; } + @Override + public TSStatus checkPermissionBeforeProcess(String userName) { + if (AuthorityChecker.SUPER_USER.equals(userName)) { + return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()); + } + return AuthorityChecker.getTSStatus( + AuthorityChecker.checkSystemPermission(userName, PrivilegeType.MAINTAIN.ordinal()), + PrivilegeType.MAINTAIN); + } + @Override public R accept(StatementVisitor visitor, C context) { return visitor.visitReconstructRegion(this, context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/RemoveRegionStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/RemoveRegionStatement.java index fae5bebad70e..186656c820d9 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/RemoveRegionStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/region/RemoveRegionStatement.java @@ -19,11 +19,15 @@ package org.apache.iotdb.db.queryengine.plan.statement.metadata.region; +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.queryengine.plan.analyze.QueryType; import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor; +import org.apache.iotdb.rpc.TSStatusCode; import java.util.Collections; import java.util.List; @@ -47,6 +51,16 @@ public int getDataNodeId() { return dataNodeId; } + @Override + public TSStatus checkPermissionBeforeProcess(String userName) { + if (AuthorityChecker.SUPER_USER.equals(userName)) { + return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()); + } + return AuthorityChecker.getTSStatus( + AuthorityChecker.checkSystemPermission(userName, PrivilegeType.MAINTAIN.ordinal()), + PrivilegeType.MAINTAIN); + } + @Override public R accept(StatementVisitor visitor, C context) { return visitor.visitRemoveRegion(this, context);