This is an automated email from the ASF dual-hosted git repository.

caogaofei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new a9d1fda50f [IOTDB-4482] IoTDB distribution: using id to delete nodes 
(#7422)
a9d1fda50f is described below

commit a9d1fda50f655923c98095a05ccf84c5d3cc6f63
Author: Caideyipi <[email protected]>
AuthorDate: Wed Sep 28 10:56:36 2022 +0800

    [IOTDB-4482] IoTDB distribution: using id to delete nodes (#7422)
---
 .../confignode/conf/ConfigNodeRemoveCheck.java     |  30 ++++-
 .../confignode/service/ConfigNodeCommandLine.java  |  11 +-
 docs/UserGuide/Cluster/Cluster-Setup.md            |  22 +---
 docs/zh/UserGuide/Cluster/Cluster-Setup.md         |  20 +---
 .../apache/iotdb/db/client/ConfigNodeClient.java   |   2 +-
 .../org/apache/iotdb/db/conf/IoTDBStopCheck.java   |  76 ------------
 .../java/org/apache/iotdb/db/service/DataNode.java |  10 +-
 .../db/service/DataNodeServerCommandLine.java      | 132 +++++++++------------
 .../apache/iotdb/db/conf/IoTDBStopCheckTest.java   | 110 -----------------
 9 files changed, 100 insertions(+), 313 deletions(-)

diff --git 
a/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeRemoveCheck.java
 
b/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeRemoveCheck.java
index d48eaaf06e..d47a3f7424 100644
--- 
a/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeRemoveCheck.java
+++ 
b/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeRemoveCheck.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.common.rpc.thrift.TEndPoint;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.BadNodeUrlException;
+import org.apache.iotdb.commons.utils.NodeUrlUtils;
 import org.apache.iotdb.confignode.client.ConfigNodeRequestType;
 import 
org.apache.iotdb.confignode.client.sync.confignode.SyncConfigNodeClientPool;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -36,6 +37,8 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Properties;
 
+import static org.apache.commons.lang3.StringUtils.isNumeric;
+
 public class ConfigNodeRemoveCheck {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(ConfigNodeStartupCheck.class);
 
@@ -50,7 +53,7 @@ public class ConfigNodeRemoveCheck {
     systemProperties = new Properties();
   }
 
-  public TConfigNodeLocation removeCheck(TEndPoint endPoint) {
+  public TConfigNodeLocation removeCheck(String args) {
     TConfigNodeLocation nodeLocation = new TConfigNodeLocation();
     if (!systemPropertiesFile.exists()) {
       LOGGER.error("The system properties file is not exists. IoTDB-ConfigNode 
is shutdown.");
@@ -58,11 +61,26 @@ public class ConfigNodeRemoveCheck {
     }
     try (FileInputStream inputStream = new 
FileInputStream(systemPropertiesFile)) {
       systemProperties.load(inputStream);
-      nodeLocation =
-          getConfigNodeList().stream()
-              .filter(e -> e.getInternalEndPoint().equals(endPoint))
-              .findFirst()
-              .orElse(null);
+      if (isNumeric(args)) {
+        int id = Integer.parseInt(args);
+        nodeLocation =
+            getConfigNodeList().stream()
+                .filter(e -> e.getConfigNodeId() == id)
+                .findFirst()
+                .orElse(null);
+      } else {
+        try {
+          TEndPoint endPoint = NodeUrlUtils.parseTEndPointUrl(args);
+          nodeLocation =
+              getConfigNodeList().stream()
+                  .filter(e -> e.getInternalEndPoint().equals(endPoint))
+                  .findFirst()
+                  .orElse(null);
+        } catch (BadNodeUrlException e2) {
+          LOGGER.info("Usage: <Node-id>/<internal_address>:<internal_port>");
+          return nodeLocation;
+        }
+      }
     } catch (IOException | BadNodeUrlException e) {
       LOGGER.error("Load system properties file failed.", e);
     }
diff --git 
a/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNodeCommandLine.java
 
b/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNodeCommandLine.java
index 3b71295da9..bb0e4ff669 100644
--- 
a/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNodeCommandLine.java
+++ 
b/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNodeCommandLine.java
@@ -19,13 +19,11 @@
 package org.apache.iotdb.confignode.service;
 
 import org.apache.iotdb.common.rpc.thrift.TConfigNodeLocation;
-import org.apache.iotdb.common.rpc.thrift.TEndPoint;
 import org.apache.iotdb.commons.ServerCommandLine;
 import org.apache.iotdb.commons.exception.BadNodeUrlException;
 import org.apache.iotdb.commons.exception.ConfigurationException;
 import org.apache.iotdb.commons.exception.StartupException;
 import org.apache.iotdb.commons.service.StartupChecks;
-import org.apache.iotdb.commons.utils.NodeUrlUtils;
 import org.apache.iotdb.confignode.conf.ConfigNodeConstant;
 import org.apache.iotdb.confignode.conf.ConfigNodeRemoveCheck;
 import org.apache.iotdb.confignode.conf.ConfigNodeStartupCheck;
@@ -97,18 +95,17 @@ public class ConfigNodeCommandLine extends 
ServerCommandLine {
 
   private void doRemoveNode(String[] args) throws IOException {
     LOGGER.info("Starting to remove {}...", ConfigNodeConstant.GLOBAL_NAME);
-    if (args.length != 3) {
-      LOGGER.info("Usage: -r <internal_address>:<internal_port>");
+    if (args.length != 2) {
+      LOGGER.info("Usage: <Node-id>/<internal_address>:<internal_port>");
       return;
     }
 
     try {
-      TEndPoint endPoint = NodeUrlUtils.parseTEndPointUrl(args[2]);
       TConfigNodeLocation removeConfigNodeLocation =
-          ConfigNodeRemoveCheck.getInstance().removeCheck(endPoint);
+          ConfigNodeRemoveCheck.getInstance().removeCheck(args[1]);
       if (removeConfigNodeLocation == null) {
         LOGGER.error(
-            "The ConfigNode to be removed is not in the cluster, please check 
the ip:port input.");
+            "The ConfigNode to be removed is not in the cluster, or the input 
format is incorrect.");
         return;
       }
 
diff --git a/docs/UserGuide/Cluster/Cluster-Setup.md 
b/docs/UserGuide/Cluster/Cluster-Setup.md
index cfdae29ade..c071443f3c 100644
--- a/docs/UserGuide/Cluster/Cluster-Setup.md
+++ b/docs/UserGuide/Cluster/Cluster-Setup.md
@@ -172,12 +172,12 @@ Execute the remove-confignode shell on an active 
ConfigNode.
 
 Remove on Linux:
 ```
-./confignode/sbin/remove-confignode.sh -r <internal_address>:<internal_port>
+./confignode/sbin/remove-confignode.sh <id>/<internal_address>:<internal_port>
 ```
 
 Remove on Windows:
 ```
-confignode\sbin\remove-confignode.bat -r <internal_address>:<internal_port>
+confignode\sbin\remove-confignode.bat <id>/<internal_address>:<internal_port>
 ```
 
 ### Remove DataNode
@@ -185,27 +185,13 @@ confignode\sbin\remove-confignode.bat -r 
<internal_address>:<internal_port>
 Execute the remove-datanode shell on an active DataNode.
 
 Remove on Linux:
-
-+ Remove a DataNode:
-```
-./datanode/sbin/remove-datanode.sh <rpc_address>:<rpc_port>
-```
-
-+ Remove multiple DataNodes:
 ```
-./datanode/sbin/remove-datanode.sh 
<rpc_address_0>:<rpc_port_0>,...,<rpc_address_n>:<rpc_port_n>
+./datanode/sbin/remove-datanode.sh <id>/<rpc_address>:<rpc_port>
 ```
 
 Remove on Windows:
-
-+ Remove a DataNode:
-```
-datanode\sbin\remove-datanode.bat <rpc_address>:<rpc_port>
-```
-
-+ Remove multiple DataNodes:
 ```
-datanode\sbin\remove-datanode.bat 
<rpc_address_0>:<rpc_port_0>,...,<rpc_address_n>:<rpc_port_n>
+datanode\sbin\remove-datanode.bat <id>/<rpc_address>:<rpc_port>
 ```
 
 ## Quick Start
diff --git a/docs/zh/UserGuide/Cluster/Cluster-Setup.md 
b/docs/zh/UserGuide/Cluster/Cluster-Setup.md
index 03aba41678..2be81f0619 100644
--- a/docs/zh/UserGuide/Cluster/Cluster-Setup.md
+++ b/docs/zh/UserGuide/Cluster/Cluster-Setup.md
@@ -173,12 +173,12 @@ datanode\sbin\start-cli.bat
 
 Linux 移除方式:
 ```
-./confignode/sbin/remove-confignode.sh -r <internal_address>:<internal_port>
+./confignode/sbin/remove-confignode.sh <id>/<internal_address>:<internal_port>
 ```
 
 Windows 移除方式:
 ```
-confignode\sbin\remove-confignode.bat -r <internal_address>:<internal_port>
+confignode\sbin\remove-confignode.bat <id>/<internal_address>:<internal_port>
 ```
 
 ### 移除 DataNode
@@ -187,26 +187,14 @@ confignode\sbin\remove-confignode.bat -r 
<internal_address>:<internal_port>
 
 Linux 移除方式:
 
-+ 移除单个 DataNode:
 ```
-./datanode/sbin/remove-datanode.sh <rpc_address>:<rpc_port>
-```
-
-+ 移除多个 DataNode:
-```
-./datanode/sbin/remove-datanode.sh 
<rpc_address_0>:<rpc_port_0>,...,<rpc_address_n>:<rpc_port_n>
+./datanode/sbin/remove-datanode.sh <id>/<rpc_address>:<rpc_port>
 ```
 
 Windows 移除方式:
 
-+ 移除单个 DataNode:
-```
-datanode\sbin\remove-datanode.bat <rpc_address>:<rpc_port>
-```
-
-+ 移除多个 DataNode:
 ```
-datanode\sbin\remove-datanode.bat 
<rpc_address_0>:<rpc_port_0>,...,<rpc_address_n>:<rpc_port_n>
+datanode\sbin\remove-datanode.bat <id>/<rpc_address>:<rpc_port>
 ```
 
 ## 快速上手
diff --git 
a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java 
b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
index 4fdb96592a..f30a46914d 100644
--- a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
+++ b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
@@ -109,7 +109,7 @@ public class ConfigNodeClient
   private static final int RETRY_NUM = 5;
 
   public static final String MSG_RECONNECTION_FAIL =
-      "Fail to connect to any config node. Please check server it";
+      "Fail to connect to any config node. Please check server status";
 
   private long connectionTimeout = 
ClientPoolProperty.DefaultProperty.WAIT_CLIENT_TIMEOUT_MS;
 
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBStopCheck.java 
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBStopCheck.java
deleted file mode 100644
index a2a7f1f51e..0000000000
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBStopCheck.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.conf;
-
-import org.apache.iotdb.commons.exception.BadNodeUrlException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class IoTDBStopCheck {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(IoTDBStopCheck.class);
-
-  public static IoTDBStopCheck getInstance() {
-    return IoTDBStopCheckHolder.INSTANCE;
-  }
-
-  private static class IoTDBStopCheckHolder {
-    private static final IoTDBStopCheck INSTANCE = new IoTDBStopCheck();
-  }
-
-  /**
-   * check datanode ips is duplicate or note
-   *
-   * @param dataNodeIps Data Node IP list
-   * @throws BadNodeUrlException check failed
-   */
-  public void checkDuplicateIp(List<String> dataNodeIps) throws 
BadNodeUrlException {
-    if (dataNodeIps == null || dataNodeIps.isEmpty()) {
-      throw new BadNodeUrlException("Data Node ips is empty");
-    }
-    long realIpNumber = dataNodeIps.stream().distinct().count();
-    if (realIpNumber != dataNodeIps.size()) {
-      throw new BadNodeUrlException("has replicate ips");
-    }
-  }
-
-  /**
-   * check the remove Data Node ips is in cluster or not
-   *
-   * @param removedDataNodeIps removed Data Node Ip list
-   * @param onlineDataNodeIps all online Data Node Ip list
-   * @throws BadNodeUrlException check failed
-   */
-  public void checkIpInCluster(List<String> removedDataNodeIps, List<String> 
onlineDataNodeIps)
-      throws BadNodeUrlException {
-    if (removedDataNodeIps == null || removedDataNodeIps.isEmpty()) {
-      throw new BadNodeUrlException("checked Data Node ips is empty");
-    }
-
-    if (onlineDataNodeIps == null || onlineDataNodeIps.isEmpty()) {
-      throw new BadNodeUrlException("online Data Node ips is empty");
-    }
-
-    if (removedDataNodeIps.stream().anyMatch(ip -> 
!onlineDataNodeIps.contains(ip))) {
-      throw new BadNodeUrlException("exist Data Node not in cluster");
-    }
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/service/DataNode.java 
b/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
index e25b510c6c..1fd5c68e1a 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
@@ -170,7 +170,7 @@ public class DataNode implements DataNodeMBean {
 
     
ConfigNodeInfo.getInstance().updateConfigNodeList(config.getTargetConfigNodeList());
     while (retry > 0) {
-      logger.info("start registering to the cluster.");
+      logger.info("Start registering to the cluster.");
       try (ConfigNodeClient configNodeClient = new ConfigNodeClient()) {
         TDataNodeRegisterReq req = new TDataNodeRegisterReq();
         req.setDataNodeConfiguration(generateDataNodeConfiguration());
@@ -247,7 +247,7 @@ public class DataNode implements DataNodeMBean {
     try {
       setUp();
     } catch (StartupException | QueryProcessException e) {
-      logger.error("meet error while starting up.", e);
+      logger.error("Meet error while starting up.", e);
       throw new StartupException("Error in activating IoTDB DataNode.");
     }
     logger.info("IoTDB DataNode has started.");
@@ -268,7 +268,7 @@ public class DataNode implements DataNodeMBean {
     setUncaughtExceptionHandler();
     initServiceProvider();
 
-    logger.info("recover the schema...");
+    logger.info("Recover the schema...");
     initSchemaEngine();
     registerManager.register(new JMXService());
     registerManager.register(FlushManager.getInstance());
@@ -389,7 +389,7 @@ public class DataNode implements DataNodeMBean {
     long time = System.currentTimeMillis();
     SchemaEngine.getInstance().init();
     long end = System.currentTimeMillis() - time;
-    logger.info("spend {}ms to recover schema.", end);
+    logger.info("Spent {}ms to recover schema.", end);
     logger.info(
         "After initializing, sequence tsFile threshold is {}, unsequence 
tsFile threshold is {}",
         config.getSeqTsFileSize(),
@@ -404,7 +404,7 @@ public class DataNode implements DataNodeMBean {
       SchemaRegionConsensusImpl.getInstance().stop();
       DataRegionConsensusImpl.getInstance().stop();
     } catch (Exception e) {
-      logger.error("stop data node error", e);
+      logger.error("Stop data node error", e);
     }
   }
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/service/DataNodeServerCommandLine.java
 
b/server/src/main/java/org/apache/iotdb/db/service/DataNodeServerCommandLine.java
index 10f11514cb..fedc46a4bf 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/service/DataNodeServerCommandLine.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/service/DataNodeServerCommandLine.java
@@ -26,13 +26,10 @@ import 
org.apache.iotdb.commons.exception.BadNodeUrlException;
 import org.apache.iotdb.commons.exception.ConfigurationException;
 import org.apache.iotdb.commons.exception.IoTDBException;
 import org.apache.iotdb.commons.utils.NodeUrlUtils;
-import org.apache.iotdb.confignode.rpc.thrift.TDataNodeConfigurationResp;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveReq;
 import org.apache.iotdb.confignode.rpc.thrift.TDataNodeRemoveResp;
 import org.apache.iotdb.db.client.ConfigNodeClient;
 import org.apache.iotdb.db.client.ConfigNodeInfo;
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.conf.IoTDBStopCheck;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.thrift.TException;
@@ -42,9 +39,10 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 
+import static org.apache.commons.lang3.StringUtils.isNumeric;
+
 public class DataNodeServerCommandLine extends ServerCommandLine {
 
   private static final Logger logger = 
LoggerFactory.getLogger(DataNodeServerCommandLine.class);
@@ -78,7 +76,7 @@ public class DataNodeServerCommandLine extends 
ServerCommandLine {
     try {
       dataNode.serverCheckAndInit();
     } catch (ConfigurationException | IOException e) {
-      logger.error("meet error when doing start checking", e);
+      logger.error("Meet error when doing start checking", e);
       return -1;
     }
     String mode = args[0];
@@ -86,7 +84,7 @@ public class DataNodeServerCommandLine extends 
ServerCommandLine {
 
     // initialize the current node and its services
     if (!dataNode.initLocalEngines()) {
-      logger.error("initLocalEngines error, stop process!");
+      logger.error("Init local engines error, stop process!");
       return -1;
     }
 
@@ -104,52 +102,22 @@ public class DataNodeServerCommandLine extends 
ServerCommandLine {
   /**
    * remove datanodes from cluster
    *
-   * @param args IPs for removed datanodes, split with ','
+   * @param args id or ip:rpc_port for removed datanode
    */
-  private void doRemoveNode(String[] args) throws Exception {
-    // throw all exception to ServerCommandLine, it used System.exit
-    removePrepare(args);
-    removeNodesFromCluster(args);
-    removeTail();
-  }
+  private void doRemoveNode(String[] args) throws BadNodeUrlException, 
TException, IoTDBException {
 
-  private void removePrepare(String[] args) throws BadNodeUrlException, 
TException {
-    ConfigNodeInfo.getInstance()
-        
.updateConfigNodeList(IoTDBDescriptor.getInstance().getConfig().getTargetConfigNodeList());
-    try (ConfigNodeClient configNodeClient = new ConfigNodeClient()) {
-      TDataNodeConfigurationResp resp = 
configNodeClient.getDataNodeConfiguration(-1);
-      // 1. online Data Node size - removed Data Node size < replication,NOT 
ALLOW remove
-      //   But replication size is set in Config Node's configuration, so 
check it in remote Config
-      // Node
-
-      // 2. removed Data Node IP not contained in below map, CAN NOT remove.
-      Map<Integer, TDataNodeConfiguration> nodeIdToNodeConfiguration =
-          resp.getDataNodeConfigurationMap();
-      List<TEndPoint> endPoints = NodeUrlUtils.parseTEndPointUrls(args[1]);
-      List<String> removedDataNodeIps =
-          
endPoints.stream().map(TEndPoint::getIp).collect(Collectors.toList());
-
-      List<String> onlineDataNodeIps =
-          nodeIdToNodeConfiguration.values().stream()
-              .map(TDataNodeConfiguration::getLocation)
-              .map(TDataNodeLocation::getInternalEndPoint)
-              .map(TEndPoint::getIp)
-              .collect(Collectors.toList());
-      IoTDBStopCheck.getInstance().checkIpInCluster(removedDataNodeIps, 
onlineDataNodeIps);
+    logger.info("Start to remove DataNode from cluster");
+    if (args.length != 2) {
+      logger.info("Usage: <node-id>/<ip>:<rpc-port>");
+      return;
     }
-  }
 
-  private void removeNodesFromCluster(String[] args)
-      throws BadNodeUrlException, TException, IoTDBException {
-    logger.info("start to remove DataNode from cluster");
+    ConfigNodeInfo.getInstance().loadConfigNodeList();
     List<TDataNodeLocation> dataNodeLocations = 
buildDataNodeLocations(args[1]);
     if (dataNodeLocations.isEmpty()) {
-      throw new BadNodeUrlException("build DataNode location is empty");
+      throw new BadNodeUrlException("No DataNode to remove");
     }
-    logger.info(
-        "There has data nodes location will be removed. size is: {}, detail: 
{}",
-        dataNodeLocations.size(),
-        dataNodeLocations);
+    logger.info("Start to remove datanode, detail:{}", dataNodeLocations);
     TDataNodeRemoveReq removeReq = new TDataNodeRemoveReq(dataNodeLocations);
     try (ConfigNodeClient configNodeClient = new ConfigNodeClient()) {
       TDataNodeRemoveResp removeResp = 
configNodeClient.removeDataNode(removeReq);
@@ -159,51 +127,67 @@ public class DataNodeServerCommandLine extends 
ServerCommandLine {
             removeResp.getStatus().toString(), 
removeResp.getStatus().getCode());
       }
       logger.info(
-          "Submit remove datanode request successfully, "
+          "Submit remove-datanode request successfully, "
               + "more details are shown in the logs of confignode-leader and 
removed-datanode, "
-              + "and after the process of remove-datanode is over, "
+              + "and after the process of removing datanode is over, "
               + "you are supposed to delete directory and data of the 
removed-datanode manually");
     }
   }
 
   /**
-   * fetch all datanode info from ConfigNode, then compare with input 'ips'
+   * fetch all datanode info from ConfigNode, then compare with input 'args'
    *
-   * @param endPorts data node ip:port, split with ','
+   * @param args datanode id or ip:rpc_port
    * @return TDataNodeLocation list
    */
-  private List<TDataNodeLocation> buildDataNodeLocations(String endPorts)
-      throws BadNodeUrlException {
+  private List<TDataNodeLocation> buildDataNodeLocations(String args) {
     List<TDataNodeLocation> dataNodeLocations = new ArrayList<>();
-    if (endPorts == null || endPorts.trim().isEmpty()) {
+    if (args == null || args.trim().isEmpty()) {
       return dataNodeLocations;
     }
 
-    List<TEndPoint> endPoints = NodeUrlUtils.parseTEndPointUrls(endPorts);
-
-    try (ConfigNodeClient client = new ConfigNodeClient()) {
-      dataNodeLocations =
-          
client.getDataNodeConfiguration(-1).getDataNodeConfigurationMap().values().stream()
-              .map(TDataNodeConfiguration::getLocation)
-              .filter(location -> 
endPoints.contains(location.getClientRpcEndPoint()))
-              .collect(Collectors.toList());
-    } catch (TException e) {
-      logger.error("Get data node locations failed", e);
-    }
-
-    if (endPoints.size() != dataNodeLocations.size()) {
-      logger.error(
-          "Build DataNode locations error, "
-              + "because number of input DataNode({}) not equals the number of 
fetched DataNodeLocations({}), "
-              + "please check your IP:RPC_PORT inputs",
-          endPoints.size(),
-          dataNodeLocations.size());
-      dataNodeLocations.clear();
+    // Now support only single datanode deletion
+    if (args.split(",").length > 1) {
+      logger.info("Incorrect input format, usage: <id>/<ip>:<rpc-port>");
       return dataNodeLocations;
     }
 
+    // Below supports multiple datanode deletion, split by ',', and is 
reserved for extension
+    try {
+      List<TEndPoint> endPoints = NodeUrlUtils.parseTEndPointUrls(args);
+      try (ConfigNodeClient client = new ConfigNodeClient()) {
+        dataNodeLocations =
+            
client.getDataNodeConfiguration(-1).getDataNodeConfigurationMap().values().stream()
+                .map(TDataNodeConfiguration::getLocation)
+                .filter(location -> 
endPoints.contains(location.getClientRpcEndPoint()))
+                .collect(Collectors.toList());
+      } catch (TException e) {
+        logger.error("Get data node locations failed", e);
+      }
+    } catch (BadNodeUrlException e) {
+      try (ConfigNodeClient client = new ConfigNodeClient()) {
+        for (String id : args.split(",")) {
+          if (!isNumeric(id)) {
+            logger.warn("Incorrect id format {}, skipped...", id);
+            continue;
+          }
+          List<TDataNodeLocation> nodeLocationResult =
+              
client.getDataNodeConfiguration(Integer.parseInt(id)).getDataNodeConfigurationMap()
+                  .values().stream()
+                  .map(TDataNodeConfiguration::getLocation)
+                  .collect(Collectors.toList());
+          if (nodeLocationResult.isEmpty()) {
+            logger.warn("DataNode {} is not in cluster, skipped...", id);
+            continue;
+          }
+          if (!dataNodeLocations.contains(nodeLocationResult.get(0))) {
+            dataNodeLocations.add(nodeLocationResult.get(0));
+          }
+        }
+      } catch (TException e1) {
+        logger.error("Get data node locations failed", e);
+      }
+    }
     return dataNodeLocations;
   }
-
-  private void removeTail() {}
 }
diff --git 
a/server/src/test/java/org/apache/iotdb/db/conf/IoTDBStopCheckTest.java 
b/server/src/test/java/org/apache/iotdb/db/conf/IoTDBStopCheckTest.java
deleted file mode 100644
index 2cdddc1952..0000000000
--- a/server/src/test/java/org/apache/iotdb/db/conf/IoTDBStopCheckTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.conf;
-
-import org.apache.iotdb.commons.exception.BadNodeUrlException;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-public class IoTDBStopCheckTest {
-  static List<String> removeIps;
-  static List<String> emptyRemoveIps;
-  static List<String> reduplicateRemoveIps;
-  static List<String> notExistRemovedIps;
-  static List<String> onlineIps;
-  static List<String> emptyOnlineIps;
-
-  @BeforeClass
-  public static void setup() {
-    onlineIps = Arrays.asList("192.168.1.1", "192.168.1.2", "192.168.1.3");
-    emptyOnlineIps = Collections.emptyList();
-
-    removeIps = Arrays.asList("192.168.1.1", "192.168.1.2");
-    notExistRemovedIps = Arrays.asList("192.168.1.1", "192.168.1.4");
-    emptyRemoveIps = Collections.emptyList();
-    reduplicateRemoveIps = Arrays.asList("192.168.1.1", "192.168.1.2", 
"192.168.1.2");
-  }
-
-  @AfterClass
-  public static void after() {
-    removeIps = null;
-    emptyRemoveIps = null;
-    reduplicateRemoveIps = null;
-    notExistRemovedIps = null;
-
-    onlineIps = null;
-    emptyOnlineIps = null;
-  }
-
-  @Test
-  public void testGetInstance() {
-    IoTDBStopCheck checker = IoTDBStopCheck.getInstance();
-    Assert.assertNotNull(checker);
-  }
-
-  @Test
-  public void testCheckDuplicateIpOK() {
-    boolean result = true;
-    try {
-      IoTDBStopCheck.getInstance().checkDuplicateIp(removeIps);
-    } catch (BadNodeUrlException e) {
-      result = false;
-    }
-    Assert.assertTrue(result);
-  }
-
-  @Test(expected = BadNodeUrlException.class)
-  public void testCheckDuplicateIpEmptyIps() throws BadNodeUrlException {
-    IoTDBStopCheck.getInstance().checkDuplicateIp(emptyRemoveIps);
-  }
-
-  @Test(expected = BadNodeUrlException.class)
-  public void testCheckDuplicateIpException() throws BadNodeUrlException {
-    IoTDBStopCheck.getInstance().checkDuplicateIp(reduplicateRemoveIps);
-  }
-
-  @Test
-  public void testCheckIpInCluster() {
-    boolean result = true;
-    try {
-      IoTDBStopCheck.getInstance().checkIpInCluster(removeIps, onlineIps);
-    } catch (BadNodeUrlException e) {
-      result = false;
-    }
-
-    Assert.assertTrue(result);
-  }
-
-  @Test(expected = BadNodeUrlException.class)
-  public void testCheckIpInClusterEmptyIp() throws BadNodeUrlException {
-    IoTDBStopCheck.getInstance().checkIpInCluster(removeIps, emptyOnlineIps);
-  }
-
-  @Test(expected = BadNodeUrlException.class)
-  public void testCheckIpInClusterException() throws BadNodeUrlException {
-    IoTDBStopCheck.getInstance().checkIpInCluster(notExistRemovedIps, 
onlineIps);
-  }
-}

Reply via email to