public DataSet removeDataNode(RemoveDataNodePlan removeDataNodePlan) {
    configManager.getProcedureManager().getEnv().getSubmitRegionMigrateLock().lock();
    LOGGER.info("NodeManager start to remove DataNode {}", removeDataNodePlan);
    try {
      // Checks if the RemoveDataNode request is valid
      RemoveDataNodeHandler removeDataNodeHandler =
          configManager.getProcedureManager().getEnv().getRemoveDataNodeHandler();
      DataNodeToStatusResp preCheckStatus =
          removeDataNodeHandler.checkRemoveDataNodeRequest(removeDataNodePlan);
      if (preCheckStatus.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
        LOGGER.error(
            "The remove DataNode request check failed. req: {}, check result: {}",
            removeDataNodePlan,
            preCheckStatus.getStatus());
        return preCheckStatus;
      }

      // Do transfer of the DataNodes before remove
      DataNodeToStatusResp dataSet = new DataNodeToStatusResp();
      if (configManager.transfer(removeDataNodePlan.getDataNodeLocations()).getCode()
          != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
        dataSet.setStatus(
            new TSStatus(TSStatusCode.REMOVE_DATANODE_ERROR.getStatusCode())
                .setMessage("Migrate the service on the removed DataNodes failed"));
        return dataSet;
      }

      // Add request to queue, then return to client
      boolean removeSucceed =
          configManager.getProcedureManager().removeDataNode(removeDataNodePlan);
      TSStatus status;
      if (removeSucceed) {
        status = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
        status.setMessage("Server accepted the request");
      } else {
        status = new TSStatus(TSStatusCode.REMOVE_DATANODE_ERROR.getStatusCode());
        status.setMessage("Server rejected the request, maybe requests are too many");
      }
      dataSet.setStatus(status);

      LOGGER.info(
          "NodeManager submit RemoveDataNodePlan finished, removeDataNodePlan: {}",
          removeDataNodePlan);
      return dataSet;
    } finally {
      configManager.getProcedureManager().getEnv().getSubmitRegionMigrateLock().unlock();
    }
  }
Removes the specified DataNodes.

@param removeDataNodePlan the plan detailing which DataNodes to remove
@return DataNodeToStatusResp, where the TSStatus will be SUCCEED_STATUS if the request is
    accepted, or DATANODE_NOT_EXIST if any DataNode does not exist.
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java