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

tanxinyu 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 9e0b62181d0 Support editing cluster name  (#12776)
9e0b62181d0 is described below

commit 9e0b62181d0d0dff4a25f011e9baf475a4cd099a
Author: Li Yu Heng <[email protected]>
AuthorDate: Fri Jun 21 15:20:58 2024 +0800

    Support editing cluster name  (#12776)
---
 .../iotdb/it/env/cluster/env/AbstractEnv.java      | 13 ++--
 .../iotdb/it/env/remote/env/RemoteServerEnv.java   |  6 ++
 .../java/org/apache/iotdb/itbase/env/BaseEnv.java  |  3 +
 .../iotdb/db/it/IoTDBSetConfigurationIT.java       | 91 +++++++++++++++++-----
 .../handlers/ConfigNodeAsyncRequestContext.java    |  6 ++
 .../confignode/conf/ConfigNodeDescriptor.java      |  6 ++
 .../confignode/conf/ConfigNodeStartupCheck.java    |  3 +-
 .../conf/ConfigNodeSystemPropertiesHandler.java    | 18 +++--
 .../confignode/conf/SystemPropertiesUtils.java     | 81 +++----------------
 .../iotdb/confignode/manager/ConfigManager.java    | 10 ++-
 .../apache/iotdb/confignode/manager/IManager.java  |  2 +
 .../manager/node/ClusterNodeStartUtils.java        | 12 +--
 .../iotdb/confignode/manager/node/NodeManager.java | 14 +++-
 .../thrift/ConfigNodeRPCServiceProcessor.java      |  5 ++
 .../db/conf/DataNodeSystemPropertiesHandler.java   | 16 ++--
 .../java/org/apache/iotdb/db/conf/IoTDBConfig.java |  9 ++-
 .../org/apache/iotdb/db/conf/IoTDBDescriptor.java  |  3 +
 .../org/apache/iotdb/db/conf/IoTDBStartCheck.java  | 12 +--
 .../iotdb/db/protocol/client/ConfigNodeClient.java |  9 ++-
 .../config/executor/ClusterConfigTaskExecutor.java |  2 +-
 .../java/org/apache/iotdb/db/service/DataNode.java |  3 +-
 .../resources/conf/iotdb-system.properties         |  4 +-
 .../iotdb/commons/conf/ConfigurationFileUtils.java | 69 ++++++++--------
 .../commons/file/SystemPropertiesHandler.java      | 62 ++++++++++-----
 .../src/main/thrift/confignode.thrift              |  5 +-
 25 files changed, 264 insertions(+), 200 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index 949a7f21fd2..54fedec8de0 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -619,6 +619,13 @@ public abstract class AbstractEnv implements BaseEnv {
     }
   }
 
+  @Override
+  public List<AbstractNodeWrapper> getNodeWrapperList() {
+    List<AbstractNodeWrapper> result = new ArrayList<>(configNodeWrapperList);
+    result.addAll(dataNodeWrapperList);
+    return result;
+  }
+
   @Override
   public List<ConfigNodeWrapper> getConfigNodeWrapperList() {
     return configNodeWrapperList;
@@ -629,12 +636,6 @@ public abstract class AbstractEnv implements BaseEnv {
     return dataNodeWrapperList;
   }
 
-  public List<AbstractNodeWrapper> getNodeWrapperList() {
-    List<AbstractNodeWrapper> result = new ArrayList<>(configNodeWrapperList);
-    result.addAll(dataNodeWrapperList);
-    return result;
-  }
-
   /**
    * Get connection to ConfigNode-Leader in ClusterIT environment
    *
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
index eae42bd7a23..b8b29544520 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
@@ -30,6 +30,7 @@ import org.apache.iotdb.isession.ISession;
 import org.apache.iotdb.isession.SessionConfig;
 import org.apache.iotdb.isession.pool.ISessionPool;
 import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.ConfigNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
 import org.apache.iotdb.it.env.remote.config.RemoteClusterConfig;
@@ -178,6 +179,11 @@ public class RemoteServerEnv implements BaseEnv {
     // Do nothing
   }
 
+  @Override
+  public List<AbstractNodeWrapper> getNodeWrapperList() {
+    return null;
+  }
+
   @Override
   public List<ConfigNodeWrapper> getConfigNodeWrapperList() {
     return null;
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
index 965e2254e84..3b9b27de851 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
@@ -25,6 +25,7 @@ import 
org.apache.iotdb.confignode.rpc.thrift.IConfigNodeRPCService;
 import org.apache.iotdb.isession.ISession;
 import org.apache.iotdb.isession.SessionConfig;
 import org.apache.iotdb.isession.pool.ISessionPool;
+import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.ConfigNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
 import org.apache.iotdb.jdbc.Constant;
@@ -133,6 +134,8 @@ public interface BaseEnv {
 
   void dumpTestJVMSnapshot();
 
+  List<AbstractNodeWrapper> getNodeWrapperList();
+
   List<ConfigNodeWrapper> getConfigNodeWrapperList();
 
   List<DataNodeWrapper> getDataNodeWrapperList();
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSetConfigurationIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSetConfigurationIT.java
index 3ab24dd94f7..1862b48d99c 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSetConfigurationIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSetConfigurationIT.java
@@ -19,13 +19,16 @@
 
 package org.apache.iotdb.db.it;
 
+import org.apache.iotdb.commons.cluster.NodeStatus;
 import org.apache.iotdb.commons.conf.CommonConfig;
+import org.apache.iotdb.confignode.rpc.thrift.IConfigNodeRPCService;
+import org.apache.iotdb.confignode.rpc.thrift.TShowClusterResp;
 import org.apache.iotdb.it.env.EnvFactory;
-import org.apache.iotdb.it.env.cluster.node.ConfigNodeWrapper;
-import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
+import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
 
+import org.awaitility.Awaitility;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -34,9 +37,13 @@ import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
 import java.io.File;
+import java.io.IOException;
 import java.nio.file.Files;
 import java.sql.Connection;
+import java.sql.ResultSet;
 import java.sql.Statement;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class})
@@ -52,7 +59,7 @@ public class IoTDBSetConfigurationIT {
   }
 
   @Test
-  public void testSetConfiguration() throws Exception {
+  public void testSetConfiguration() {
     try (Connection connection = EnvFactory.getEnv().getConnection();
         Statement statement = connection.createStatement()) {
       statement.execute("set configuration 
\"enable_seq_space_compaction\"=\"false\"");
@@ -61,29 +68,73 @@ public class IoTDBSetConfigurationIT {
     } catch (Exception e) {
       Assert.fail(e.getMessage());
     }
-    for (ConfigNodeWrapper configNodeWrapper : 
EnvFactory.getEnv().getConfigNodeWrapperList()) {
-      String systemPropertiesPath =
-          configNodeWrapper.getNodePath()
-              + File.separator
-              + "conf"
-              + File.separator
-              + CommonConfig.SYSTEM_CONFIG_NAME;
-      File f = new File(systemPropertiesPath);
-      String content = new String(Files.readAllBytes(f.toPath()));
-      Assert.assertTrue(content.contains("enable_seq_space_compaction=false"));
-      
Assert.assertTrue(content.contains("enable_unseq_space_compaction=false"));
-    }
-    for (DataNodeWrapper dataNodeWrapper : 
EnvFactory.getEnv().getDataNodeWrapperList()) {
+    Assert.assertTrue(
+        EnvFactory.getEnv().getConfigNodeWrapperList().stream()
+            .allMatch(
+                nodeWrapper ->
+                    checkConfigFileContains(
+                        nodeWrapper,
+                        "enable_seq_space_compaction=false",
+                        "enable_unseq_space_compaction=false")));
+    Assert.assertTrue(
+        EnvFactory.getEnv().getDataNodeWrapperList().stream()
+            .allMatch(
+                nodeWrapper ->
+                    checkConfigFileContains(
+                        nodeWrapper,
+                        "enable_seq_space_compaction=false",
+                        "enable_cross_space_compaction=false")));
+  }
+
+  @Test
+  public void testSetClusterName() throws Exception {
+    Connection connection = EnvFactory.getEnv().getConnection();
+    Statement statement = connection.createStatement();
+    // set cluster name on cn and dn
+    statement.execute("set configuration \"cluster_name\"=\"xx\"");
+    ResultSet variables = statement.executeQuery("show variables");
+    variables.next();
+    Assert.assertEquals("xx", variables.getString(2));
+    Assert.assertTrue(
+        EnvFactory.getEnv().getNodeWrapperList().stream()
+            .allMatch(nodeWrapper -> checkConfigFileContains(nodeWrapper, 
"cluster_name=xx")));
+    // restart successfully
+    EnvFactory.getEnv().getDataNodeWrapper(0).stop();
+    EnvFactory.getEnv().getDataNodeWrapper(0).start();
+    IConfigNodeRPCService.Iface configNodeClient =
+        EnvFactory.getEnv().getLeaderConfigNodeConnection();
+    Awaitility.await()
+        .atMost(10, TimeUnit.SECONDS)
+        .until(
+            () -> {
+              TShowClusterResp resp = configNodeClient.showCluster();
+              return 
NodeStatus.Running.toString().equals(resp.getNodeStatus().get(1));
+            });
+    // set cluster name on datanode, cannot restart
+    statement.execute("set configuration \"cluster_name\"=\"yy\" on 1");
+    EnvFactory.getEnv().getDataNodeWrapper(0).stop();
+    EnvFactory.getEnv().getDataNodeWrapper(0).start();
+    Awaitility.await()
+        .atMost(10, TimeUnit.SECONDS)
+        .until(() -> !EnvFactory.getEnv().getDataNodeWrapper(0).isAlive());
+    Assert.assertTrue(
+        checkConfigFileContains(EnvFactory.getEnv().getDataNodeWrapper(0), 
"cluster_name=yy"));
+  }
+
+  private static boolean checkConfigFileContains(
+      AbstractNodeWrapper nodeWrapper, String... contents) {
+    try {
       String systemPropertiesPath =
-          dataNodeWrapper.getNodePath()
+          nodeWrapper.getNodePath()
               + File.separator
               + "conf"
               + File.separator
               + CommonConfig.SYSTEM_CONFIG_NAME;
       File f = new File(systemPropertiesPath);
-      String content = new String(Files.readAllBytes(f.toPath()));
-      Assert.assertTrue(content.contains("enable_seq_space_compaction=false"));
-      
Assert.assertTrue(content.contains("enable_cross_space_compaction=false"));
+      String fileContent = new String(Files.readAllBytes(f.toPath()));
+      return Arrays.stream(contents).allMatch(fileContent::contains);
+    } catch (IOException ignore) {
+      return false;
     }
   }
 }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/ConfigNodeAsyncRequestContext.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/ConfigNodeAsyncRequestContext.java
index cde2cf1c8ec..e87d0f002e3 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/ConfigNodeAsyncRequestContext.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/ConfigNodeAsyncRequestContext.java
@@ -34,6 +34,12 @@ import java.util.Map;
 public class ConfigNodeAsyncRequestContext<Q, R>
     extends AsyncRequestContext<Q, R, CnToCnNodeRequestType, 
TConfigNodeLocation> {
 
+  public ConfigNodeAsyncRequestContext(
+      CnToCnNodeRequestType cnToCnRequestType,
+      Map<Integer, TConfigNodeLocation> integerTConfigNodeLocationMap) {
+    super(cnToCnRequestType, integerTConfigNodeLocationMap);
+  }
+
   public ConfigNodeAsyncRequestContext(
       CnToCnNodeRequestType configNodeRequestType,
       Q q,
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeDescriptor.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeDescriptor.java
index e73ab25debe..817469513e1 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeDescriptor.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeDescriptor.java
@@ -45,6 +45,7 @@ import java.net.URL;
 import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.Properties;
 
 public class ConfigNodeDescriptor {
@@ -871,6 +872,11 @@ public class ConfigNodeDescriptor {
     }
   }
 
+  public void loadHotModifiedProps(Properties properties) {
+    Optional.ofNullable(properties.getProperty(IoTDBConstant.CLUSTER_NAME))
+        .ifPresent(conf::setClusterName);
+  }
+
   public static ConfigNodeDescriptor getInstance() {
     return ConfigNodeDescriptorHolder.INSTANCE;
   }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeStartupCheck.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeStartupCheck.java
index 9a42264ed93..245e04934b6 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeStartupCheck.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeStartupCheck.java
@@ -74,8 +74,7 @@ public class ConfigNodeStartupCheck extends StartupChecks {
     checkGlobalConfig();
     createDirsIfNecessary();
     if (SystemPropertiesUtils.isRestarted()) {
-      /* Always restore ClusterName and ConfigNodeId first */
-      
CONF.setClusterName(SystemPropertiesUtils.loadClusterNameWhenRestarted());
+      /* Always restore ConfigNodeId first */
       
CONF.setConfigNodeId(SystemPropertiesUtils.loadConfigNodeIdWhenRestarted());
 
       SystemPropertiesUtils.checkSystemProperties();
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeSystemPropertiesHandler.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeSystemPropertiesHandler.java
index b92e2e57e05..2fd9969fd71 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeSystemPropertiesHandler.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/ConfigNodeSystemPropertiesHandler.java
@@ -36,14 +36,18 @@ public class ConfigNodeSystemPropertiesHandler extends 
SystemPropertiesHandler {
     super(filePath);
   }
 
-  public static synchronized SystemPropertiesHandler getInstance() {
+  public static SystemPropertiesHandler getInstance() {
     if (INSTANCE == null) {
-      INSTANCE =
-          new ConfigNodeSystemPropertiesHandler(
-              ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
-                  + File.separator
-                  + ConfigNodeConstant.SYSTEM_FILE_NAME);
-      INSTANCE.recover();
+      synchronized (ConfigNodeSystemPropertiesHandler.class) {
+        if (INSTANCE == null) {
+          INSTANCE =
+              new ConfigNodeSystemPropertiesHandler(
+                  ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
+                      + File.separator
+                      + ConfigNodeConstant.SYSTEM_FILE_NAME);
+          INSTANCE.init();
+        }
+      }
     }
     return INSTANCE;
   }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/SystemPropertiesUtils.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/SystemPropertiesUtils.java
index a56f4a63f72..65e05bccfac 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/SystemPropertiesUtils.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/SystemPropertiesUtils.java
@@ -37,14 +37,11 @@ import java.util.List;
 import java.util.Objects;
 import java.util.Properties;
 
-import static org.apache.iotdb.commons.conf.IoTDBConstant.CLUSTER_NAME;
-import static org.apache.iotdb.commons.conf.IoTDBConstant.DEFAULT_CLUSTER_NAME;
-
 public class SystemPropertiesUtils {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(SystemPropertiesUtils.class);
 
-  private static SystemPropertiesHandler systemPropertiesHandler =
+  private static final SystemPropertiesHandler systemPropertiesHandler =
       ConfigNodeSystemPropertiesHandler.getInstance();
 
   private static final ConfigNodeConfig conf = 
ConfigNodeDescriptor.getInstance().getConf();
@@ -90,31 +87,17 @@ public class SystemPropertiesUtils {
    */
   public static void checkSystemProperties() throws IOException {
     Properties systemProperties = systemPropertiesHandler.read();
-    boolean needReWrite = false;
     final String format =
         "[SystemProperties] The parameter \"{}\" can't be modified after first 
startup."
             + " Your configuration: {} will be forced update to: {}";
 
-    // Cluster configuration
-    String clusterName = systemProperties.getProperty(CLUSTER_NAME, null);
-    if (clusterName == null) {
-      needReWrite = true;
-    } else if (!clusterName.equals(conf.getClusterName())) {
-      LOGGER.warn(format, CLUSTER_NAME, conf.getClusterName(), clusterName);
-      conf.setClusterName(clusterName);
-    }
-
     String internalAddress = systemProperties.getProperty(CN_INTERNAL_ADDRESS, 
null);
-    if (internalAddress == null) {
-      needReWrite = true;
-    } else if (!internalAddress.equals(conf.getInternalAddress())) {
+    if (!internalAddress.equals(conf.getInternalAddress())) {
       LOGGER.warn(format, CN_INTERNAL_ADDRESS, conf.getInternalAddress(), 
internalAddress);
       conf.setInternalAddress(internalAddress);
     }
 
-    if (systemProperties.getProperty(CN_INTERNAL_PORT, null) == null) {
-      needReWrite = true;
-    } else {
+    if (systemProperties.getProperty(CN_INTERNAL_PORT, null) != null) {
       int internalPort = 
Integer.parseInt(systemProperties.getProperty(CN_INTERNAL_PORT));
       if (internalPort != conf.getInternalPort()) {
         LOGGER.warn(format, CN_INTERNAL_PORT, conf.getInternalPort(), 
internalPort);
@@ -122,9 +105,7 @@ public class SystemPropertiesUtils {
       }
     }
 
-    if (systemProperties.getProperty(CN_CONSENSUS_PORT, null) == null) {
-      needReWrite = true;
-    } else {
+    if (systemProperties.getProperty(CN_CONSENSUS_PORT, null) != null) {
       int consensusPort = 
Integer.parseInt(systemProperties.getProperty(CN_CONSENSUS_PORT));
       if (consensusPort != conf.getConsensusPort()) {
         LOGGER.warn(format, CN_CONSENSUS_PORT, conf.getConsensusPort(), 
consensusPort);
@@ -132,9 +113,7 @@ public class SystemPropertiesUtils {
       }
     }
 
-    if (systemProperties.getProperty(TIMESTAMP_PRECISION, null) == null) {
-      needReWrite = true;
-    } else {
+    if (systemProperties.getProperty(TIMESTAMP_PRECISION, null) != null) {
       String timestampPrecision = 
systemProperties.getProperty(TIMESTAMP_PRECISION);
       if (!timestampPrecision.equals(COMMON_CONFIG.getTimestampPrecision())) {
         LOGGER.warn(
@@ -146,10 +125,7 @@ public class SystemPropertiesUtils {
     // Consensus protocol configuration
     String configNodeConsensusProtocolClass =
         systemProperties.getProperty(CN_CONSENSUS_PROTOCOL, null);
-    if (configNodeConsensusProtocolClass == null) {
-      needReWrite = true;
-    } else if (!configNodeConsensusProtocolClass.equals(
-        conf.getConfigNodeConsensusProtocolClass())) {
+    if 
(!configNodeConsensusProtocolClass.equals(conf.getConfigNodeConsensusProtocolClass()))
 {
       LOGGER.warn(
           format,
           CN_CONSENSUS_PROTOCOL,
@@ -160,10 +136,7 @@ public class SystemPropertiesUtils {
 
     String dataRegionConsensusProtocolClass =
         systemProperties.getProperty(DATA_CONSENSUS_PROTOCOL, null);
-    if (dataRegionConsensusProtocolClass == null) {
-      needReWrite = true;
-    } else if (!dataRegionConsensusProtocolClass.equals(
-        conf.getDataRegionConsensusProtocolClass())) {
+    if 
(!dataRegionConsensusProtocolClass.equals(conf.getDataRegionConsensusProtocolClass()))
 {
       LOGGER.warn(
           format,
           DATA_CONSENSUS_PROTOCOL,
@@ -174,10 +147,7 @@ public class SystemPropertiesUtils {
 
     String schemaRegionConsensusProtocolClass =
         systemProperties.getProperty(SCHEMA_CONSENSUS_PROTOCOL, null);
-    if (schemaRegionConsensusProtocolClass == null) {
-      needReWrite = true;
-    } else if (!schemaRegionConsensusProtocolClass.equals(
-        conf.getSchemaRegionConsensusProtocolClass())) {
+    if 
(!schemaRegionConsensusProtocolClass.equals(conf.getSchemaRegionConsensusProtocolClass()))
 {
       LOGGER.warn(
           format,
           SCHEMA_CONSENSUS_PROTOCOL,
@@ -187,9 +157,7 @@ public class SystemPropertiesUtils {
     }
 
     // PartitionSlot configuration
-    if (systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM, null) == null) 
{
-      needReWrite = true;
-    } else {
+    if (systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM, null) != null) 
{
       int seriesPartitionSlotNum =
           
Integer.parseInt(systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM));
       if (seriesPartitionSlotNum != conf.getSeriesSlotNum()) {
@@ -200,10 +168,7 @@ public class SystemPropertiesUtils {
 
     String seriesPartitionSlotExecutorClass =
         systemProperties.getProperty(SERIES_PARTITION_EXECUTOR_CLASS, null);
-    if (seriesPartitionSlotExecutorClass == null) {
-      needReWrite = true;
-    } else if (!Objects.equals(
-        seriesPartitionSlotExecutorClass, 
conf.getSeriesPartitionExecutorClass())) {
+    if (!Objects.equals(seriesPartitionSlotExecutorClass, 
conf.getSeriesPartitionExecutorClass())) {
       LOGGER.warn(
           format,
           SERIES_PARTITION_EXECUTOR_CLASS,
@@ -212,9 +177,7 @@ public class SystemPropertiesUtils {
       conf.setSeriesPartitionExecutorClass(seriesPartitionSlotExecutorClass);
     }
 
-    if (systemProperties.getProperty(TIME_PARTITION_INTERVAL, null) == null) {
-      needReWrite = true;
-    } else {
+    if (systemProperties.getProperty(TIME_PARTITION_INTERVAL, null) != null) {
       long timePartitionInterval =
           
Long.parseLong(systemProperties.getProperty(TIME_PARTITION_INTERVAL));
       if (timePartitionInterval != COMMON_CONFIG.getTimePartitionInterval()) {
@@ -261,8 +224,6 @@ public class SystemPropertiesUtils {
     systemProperties.setProperty("commit_id", IoTDBConstant.BUILD_INFO);
 
     // Cluster configuration
-    systemProperties.setProperty("cluster_name", conf.getClusterName());
-    LOGGER.info("[SystemProperties] store cluster_name: {}", 
conf.getClusterName());
     systemProperties.setProperty("config_node_id", 
String.valueOf(conf.getConfigNodeId()));
     LOGGER.info("[SystemProperties] store config_node_id: {}", 
conf.getConfigNodeId());
     systemProperties.setProperty(
@@ -321,26 +282,6 @@ public class SystemPropertiesUtils {
         "config_node_list", NodeUrlUtils.convertTConfigNodeUrls(configNodes));
   }
 
-  /**
-   * Load the cluster_name in confignode-system.properties file. We only 
invoke this interface when
-   * restarted.
-   *
-   * @return The property of cluster_name in confignode-system.properties file
-   * @throws IOException When load confignode-system.properties file failed
-   */
-  public static String loadClusterNameWhenRestarted() throws IOException {
-    Properties systemProperties = systemPropertiesHandler.read();
-    String clusterName = systemProperties.getProperty(CLUSTER_NAME, null);
-    if (clusterName == null) {
-      LOGGER.warn(
-          "Lack cluster_name field in "
-              + "data/confignode/system/confignode-system.properties, set it 
as defaultCluster");
-      systemProperties.setProperty(CLUSTER_NAME, DEFAULT_CLUSTER_NAME);
-      return systemProperties.getProperty(CLUSTER_NAME, null);
-    }
-    return clusterName;
-  }
-
   /**
    * Load the config_node_id in confignode-system.properties file. We only 
invoke this interface
    * when restarted.
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index 7bb252fe8ac..69b21829237 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -1509,6 +1509,7 @@ public class ConfigManager implements IManager {
       } catch (Exception e) {
         return RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR, 
e.getMessage());
       }
+      ConfigNodeDescriptor.getInstance().loadHotModifiedProps(properties);
       if (CONF.getConfigNodeId() == req.getNodeId()) {
         return tsStatus;
       }
@@ -1536,13 +1537,18 @@ public class ConfigManager implements IManager {
   }
 
   @Override
-  public TSStatus loadConfiguration() {
+  public TSStatus submitLoadConfigurationTask() {
     TSStatus status = confirmLeader();
     return status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()
-        ? RpcUtils.squashResponseStatusList(nodeManager.loadConfiguration())
+        ? 
RpcUtils.squashResponseStatusList(nodeManager.submitLoadConfigurationTask())
         : status;
   }
 
+  @Override
+  public TSStatus loadConfiguration() {
+    throw new UnsupportedOperationException("not implement yet");
+  }
+
   @Override
   public TShowConfigurationResp showConfiguration(int nodeId) {
     if (ConfigNodeDescriptor.getInstance().getConf().getConfigNodeId() == 
nodeId) {
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
index 98695d1eb7b..3df54d41cf7 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
@@ -490,6 +490,8 @@ public interface IManager {
   /** Stop repair data task */
   TSStatus stopRepairData();
 
+  TSStatus submitLoadConfigurationTask();
+
   /** Load configuration on all DataNodes. */
   TSStatus loadConfiguration();
 
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/ClusterNodeStartUtils.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/ClusterNodeStartUtils.java
index 1230746e357..035517172f3 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/ClusterNodeStartUtils.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/ClusterNodeStartUtils.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.cluster.NodeType;
 import org.apache.iotdb.commons.conf.CommonConfig;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.confignode.conf.ConfigNodeConfig;
 import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
 import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
@@ -41,8 +42,7 @@ import java.util.Set;
 /** Startup check utils before register/restart a ConfigNode/DataNode. */
 public class ClusterNodeStartUtils {
 
-  private static final String CLUSTER_NAME =
-      ConfigNodeDescriptor.getInstance().getConf().getClusterName();
+  private static final ConfigNodeConfig CONF = 
ConfigNodeDescriptor.getInstance().getConf();
 
   private static final String POSSIBLE_SOLUTIONS = " Possible solutions are as 
follows:\r\n";
 
@@ -58,7 +58,7 @@ public class ClusterNodeStartUtils {
 
   private static TSStatus confirmClusterName(NodeType nodeType, String 
clusterName) {
     TSStatus status = new TSStatus();
-    if (!CLUSTER_NAME.equals(clusterName)) {
+    if (!CONF.getClusterName().equals(clusterName)) {
       status.setCode(TSStatusCode.REJECT_NODE_START.getStatusCode());
       status.setMessage(
           String.format(
@@ -70,7 +70,7 @@ public class ClusterNodeStartUtils {
               nodeType.getNodeType(),
               nodeType.getNodeType(),
               clusterName,
-              CLUSTER_NAME,
+              CONF.getClusterName(),
               CommonConfig.SYSTEM_CONFIG_NAME,
               CommonConfig.SYSTEM_CONFIG_NAME));
       return status;
@@ -168,7 +168,7 @@ public class ClusterNodeStartUtils {
     TSStatus status = new TSStatus();
 
     /* Reject restart if the cluster name is error */
-    if (!CLUSTER_NAME.equals(clusterName)) {
+    if (!CONF.getClusterName().equals(clusterName)) {
       status.setCode(TSStatusCode.REJECT_NODE_START.getStatusCode());
       status.setMessage(
           String.format(
@@ -180,7 +180,7 @@ public class ClusterNodeStartUtils {
               nodeType.getNodeType(),
               nodeType.getNodeType(),
               clusterName,
-              CLUSTER_NAME,
+              CONF.getClusterName(),
               CommonConfig.SYSTEM_CONFIG_NAME,
               CommonConfig.SYSTEM_CONFIG_NAME));
       return status;
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
index c8b946cf226..19c630f2188 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
@@ -498,6 +498,11 @@ public class NodeManager {
     return dataNodeLocations;
   }
 
+  public Map<Integer, TConfigNodeLocation> getRegisteredConfigNodeLocations() {
+    return nodeInfo.getRegisteredConfigNodes().stream()
+        .collect(Collectors.toMap(TConfigNodeLocation::getConfigNodeId, 
location -> location));
+  }
+
   public List<TDataNodeInfo> getRegisteredDataNodeInfoList() {
     List<TDataNodeInfo> dataNodeInfoList = new ArrayList<>();
     List<TDataNodeConfiguration> registeredDataNodes = 
this.getRegisteredDataNodes();
@@ -787,14 +792,15 @@ public class NodeManager {
     return clientHandler.getResponseList();
   }
 
-  public List<TSStatus> loadConfiguration() {
+  public List<TSStatus> submitLoadConfigurationTask() {
     Map<Integer, TDataNodeLocation> dataNodeLocationMap =
         configManager.getNodeManager().getRegisteredDataNodeLocations();
-    DataNodeAsyncRequestContext<Object, TSStatus> clientHandler =
+    DataNodeAsyncRequestContext<Object, TSStatus> dataNodeRequestContext =
         new DataNodeAsyncRequestContext<>(
             CnToDnRequestType.LOAD_CONFIGURATION, dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    return clientHandler.getResponseList();
+    CnToDnInternalServiceAsyncRequestManager.getInstance()
+        .sendAsyncRequestWithRetry(dataNodeRequestContext);
+    return dataNodeRequestContext.getResponseList();
   }
 
   public TShowConfigurationResp showConfiguration(int nodeId) {
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 385678b7ccd..70c6aa7fba7 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -830,6 +830,11 @@ public class ConfigNodeRPCServiceProcessor implements 
IConfigNodeRPCService.Ifac
     return configManager.stopRepairData();
   }
 
+  @Override
+  public TSStatus submitLoadConfigurationTask() throws TException {
+    return configManager.submitLoadConfigurationTask();
+  }
+
   @Override
   public TSStatus loadConfiguration() {
     return configManager.loadConfiguration();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/DataNodeSystemPropertiesHandler.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/DataNodeSystemPropertiesHandler.java
index 2c9d6e5e535..4190fb89f6f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/DataNodeSystemPropertiesHandler.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/DataNodeSystemPropertiesHandler.java
@@ -38,14 +38,16 @@ public class DataNodeSystemPropertiesHandler extends 
SystemPropertiesHandler {
     super(filePath);
   }
 
-  public static synchronized SystemPropertiesHandler getInstance() {
+  public static SystemPropertiesHandler getInstance() {
     if (INSTANCE == null) {
-      INSTANCE =
-          new DataNodeSystemPropertiesHandler(
-              IoTDBDescriptor.getInstance().getConfig().getSystemDir()
-                  + File.separator
-                  + PROPERTIES_FILE_NAME);
-      INSTANCE.recover();
+      synchronized (DataNodeSystemPropertiesHandler.class) {
+        INSTANCE =
+            new DataNodeSystemPropertiesHandler(
+                IoTDBDescriptor.getInstance().getConfig().getSystemDir()
+                    + File.separator
+                    + PROPERTIES_FILE_NAME);
+        INSTANCE.init();
+      }
     }
     return INSTANCE;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index 3e3fa348ed6..2f574d9236c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -61,7 +61,6 @@ import java.io.IOException;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Properties;
@@ -1336,9 +1335,13 @@ public class IoTDBConfig {
     formulateDataDirs(tierDataDirs);
     // make sure old data directories not removed
     for (int i = 0; i < this.tierDataDirs.length; ++i) {
-      HashSet<String> newDirs = new HashSet<>(Arrays.asList(tierDataDirs[i]));
+      List<String> newDirs = Arrays.asList(tierDataDirs[i]);
       for (String oldDir : this.tierDataDirs[i]) {
-        if (!newDirs.contains(oldDir)) {
+        if (newDirs.stream()
+            .noneMatch(
+                newDir ->
+                    Objects.equals(
+                        new File(newDir).getAbsolutePath(), new 
File(oldDir).getAbsolutePath()))) {
           String msg =
               String.format("%s is removed from data_dirs parameter, please 
add it back.", oldDir);
           logger.error(msg);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index dcf8792a145..3be8e0755a6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -1729,6 +1729,9 @@ public class IoTDBDescriptor {
 
       // update tsfile-format config
       loadTsFileProps(properties);
+      // update cluster name
+      conf.setClusterName(
+          properties.getProperty(IoTDBConstant.CLUSTER_NAME, 
conf.getClusterName()));
       // update slow_query_threshold
       conf.setSlowQueryThreshold(
           Long.parseLong(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBStartCheck.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBStartCheck.java
index a91a8d7f7fc..ca08c7bbb23 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBStartCheck.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBStartCheck.java
@@ -261,18 +261,13 @@ public class IoTDBStartCheck {
     }
 
     // load configuration from system properties only when start as Data node
-    if (properties.containsKey(IoTDBConstant.CLUSTER_NAME)) {
-      
config.setClusterName(properties.getProperty(IoTDBConstant.CLUSTER_NAME));
-    }
     if (properties.containsKey(DATA_NODE_ID)) {
       
config.setDataNodeId(Integer.parseInt(properties.getProperty(DATA_NODE_ID)));
     }
-
     if (properties.containsKey(SCHEMA_REGION_CONSENSUS_PROTOCOL)) {
       config.setSchemaRegionConsensusProtocolClass(
           properties.getProperty(SCHEMA_REGION_CONSENSUS_PROTOCOL));
     }
-
     if (properties.containsKey(DATA_REGION_CONSENSUS_PROTOCOL)) {
       config.setDataRegionConsensusProtocolClass(
           properties.getProperty(DATA_REGION_CONSENSUS_PROTOCOL));
@@ -287,11 +282,8 @@ public class IoTDBStartCheck {
         parameter + "can't be modified after first startup");
   }
 
-  /** call this method to serialize ClusterName and DataNodeId */
-  public void serializeClusterNameAndDataNodeId(String clusterName, int 
dataNodeId)
-      throws IOException {
-    systemPropertiesHandler.put(
-        IoTDBConstant.CLUSTER_NAME, clusterName, DATA_NODE_ID, 
String.valueOf(dataNodeId));
+  public void serializeDataNodeId(int dataNodeId) throws IOException {
+    systemPropertiesHandler.put(DATA_NODE_ID, String.valueOf(dataNodeId));
   }
 
   public boolean checkConsensusProtocolExists(TConsensusGroupType type) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
index e4af46f510a..43e30e515e8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
@@ -671,9 +671,14 @@ public class ConfigNodeClient implements 
IConfigNodeRPCService.Iface, ThriftClie
   }
 
   @Override
-  public TSStatus loadConfiguration() throws TException {
+  public TSStatus submitLoadConfigurationTask() throws TException {
     return executeRemoteCallWithRetry(
-        () -> client.loadConfiguration(), status -> 
!updateConfigNodeLeader(status));
+        () -> client.submitLoadConfigurationTask(), status -> 
!updateConfigNodeLeader(status));
+  }
+
+  @Override
+  public TSStatus loadConfiguration() throws TException {
+    throw new UnsupportedOperationException("Please call 
submitLoadConfigurationTask instead");
   }
 
   @Override
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 6c9571599f9..dffec9f9dce 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
@@ -1161,7 +1161,7 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
       try (ConfigNodeClient client =
           
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
         // Send request to some API server
-        tsStatus = client.loadConfiguration();
+        tsStatus = client.submitLoadConfigurationTask();
       } catch (ClientManagerException | TException e) {
         future.setException(e);
       }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
index f197e4420ea..c06a838e9e6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
@@ -443,8 +443,7 @@ public class DataNode implements DataNodeMBean {
       /* Store runtime configurations when register success */
       int dataNodeID = dataNodeRegisterResp.getDataNodeId();
       config.setDataNodeId(dataNodeID);
-      IoTDBStartCheck.getInstance()
-          .serializeClusterNameAndDataNodeId(config.getClusterName(), 
dataNodeID);
+      IoTDBStartCheck.getInstance().serializeDataNodeId(dataNodeID);
 
       storeRuntimeConfigurations(
           dataNodeRegisterResp.getConfigNodeList(), 
dataNodeRegisterResp.getRuntimeConfiguration());
diff --git 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties
index 7dbf5f5b716..c0b71df98ec 100644
--- 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties
+++ 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties
@@ -539,7 +539,9 @@ dn_metric_prometheus_reporter_port=9092
 ####################
 
 # Used for indicate cluster name and distinguish different cluster.
-# effectiveMode: first_start
+# If you need to modify the cluster name, it's recommended to use 'set 
configuration "cluster_name=xxx"' sql.
+# Manually modifying configuration file is not recommended, which may cause 
node restart fail.
+# effectiveMode: restart
 # Datatype: string
 cluster_name=defaultCluster
 
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/ConfigurationFileUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/ConfigurationFileUtils.java
index d4c50a92abf..ff317fbe90b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/ConfigurationFileUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/ConfigurationFileUtils.java
@@ -88,7 +88,6 @@ public class ConfigurationFileUtils {
               "dn_data_region_consensus_port",
               "dn_seed_config_node",
               "dn_session_timeout_threshold",
-              "cluster_name",
               "config_node_consensus_protocol_class",
               "schema_replication_factor",
               "data_replication_factor",
@@ -188,46 +187,46 @@ public class ConfigurationFileUtils {
 
   public static void updateConfigurationFile(File file, Properties 
newConfigItems)
       throws IOException, InterruptedException {
-    // read configuration file
-    List<String> lines = new ArrayList<>();
-    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
-      String line = null;
-      while ((line = reader.readLine()) != null) {
-        lines.add(line);
-      }
-    }
-    // generate new configuration file content in memory
-    StringBuilder contentsOfNewConfigurationFile = new StringBuilder();
-    for (String currentLine : lines) {
-      if (currentLine.trim().isEmpty() || currentLine.trim().startsWith("#")) {
-        
contentsOfNewConfigurationFile.append(currentLine).append(lineSeparator);
-        continue;
+    File lockFile = new File(file.getPath() + lockFileSuffix);
+    acquireTargetFileLock(lockFile);
+    try {
+      // read configuration file
+      List<String> lines = new ArrayList<>();
+      try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+        String line = null;
+        while ((line = reader.readLine()) != null) {
+          lines.add(line);
+        }
       }
-      int equalsIndex = currentLine.indexOf('=');
-      // replace old config
-      if (equalsIndex != -1) {
-        String key = currentLine.substring(0, equalsIndex).trim();
-        String value = currentLine.substring(equalsIndex + 1).trim();
-        if (!newConfigItems.containsKey(key)) {
+      // generate new configuration file content in memory
+      StringBuilder contentsOfNewConfigurationFile = new StringBuilder();
+      for (String currentLine : lines) {
+        if (currentLine.trim().isEmpty() || 
currentLine.trim().startsWith("#")) {
           
contentsOfNewConfigurationFile.append(currentLine).append(lineSeparator);
           continue;
         }
-        if (newConfigItems.getProperty(key).equals(value)) {
-          
contentsOfNewConfigurationFile.append(currentLine).append(lineSeparator);
-          newConfigItems.remove(key);
-        } else {
-          
contentsOfNewConfigurationFile.append("#").append(currentLine).append(lineSeparator);
+        int equalsIndex = currentLine.indexOf('=');
+        // replace old config
+        if (equalsIndex != -1) {
+          String key = currentLine.substring(0, equalsIndex).trim();
+          String value = currentLine.substring(equalsIndex + 1).trim();
+          if (!newConfigItems.containsKey(key)) {
+            
contentsOfNewConfigurationFile.append(currentLine).append(lineSeparator);
+            continue;
+          }
+          if (newConfigItems.getProperty(key).equals(value)) {
+            
contentsOfNewConfigurationFile.append(currentLine).append(lineSeparator);
+            newConfigItems.remove(key);
+          } else {
+            
contentsOfNewConfigurationFile.append("#").append(currentLine).append(lineSeparator);
+          }
         }
       }
-    }
-    if (newConfigItems.isEmpty()) {
-      // No configuration needs to be modified
-      return;
-    }
-    File lockFile = new File(file.getPath() + lockFileSuffix);
-    acquireTargetFileLock(lockFile);
-    logger.info("Updating configuration file {}", file.getAbsolutePath());
-    try {
+      if (newConfigItems.isEmpty()) {
+        // No configuration needs to be modified
+        return;
+      }
+      logger.info("Updating configuration file {}", file.getAbsolutePath());
       try (BufferedWriter writer = new BufferedWriter(new 
FileWriter(lockFile))) {
         writer.write(contentsOfNewConfigurationFile.toString());
         // Properties.store is not used as Properties.store may generate '\' 
automatically
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/file/SystemPropertiesHandler.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/file/SystemPropertiesHandler.java
index 39de4da3a35..35aacd0b5c2 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/file/SystemPropertiesHandler.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/file/SystemPropertiesHandler.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.commons.file;
 
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+
 import org.apache.ratis.util.AutoCloseableLock;
 import org.apache.ratis.util.FileUtils;
 import org.slf4j.Logger;
@@ -94,6 +96,18 @@ public abstract class SystemPropertiesHandler {
     }
   }
 
+  public void remove(String key) throws IOException {
+    try (AutoCloseableLock ignore = 
AutoCloseableLock.acquire(lock.writeLock())) {
+      Properties properties = readWithoutLock(formalFile);
+      if (!properties.containsKey(key)) {
+        return;
+      }
+      properties.remove(key);
+      writeWithoutLock(properties, tmpFile);
+      replaceFormalFile();
+    }
+  }
+
   private void writeWithoutLock(Properties properties, File file) throws 
IOException {
     try (FileOutputStream fileOutputStream = new FileOutputStream(file);
         Writer writer = new OutputStreamWriter(fileOutputStream, 
StandardCharsets.UTF_8)) {
@@ -123,31 +137,37 @@ public abstract class SystemPropertiesHandler {
     return !fileExist();
   }
 
-  protected void recover() {
+  protected void init() {
     try (AutoCloseableLock ignore = 
AutoCloseableLock.acquire(lock.writeLock())) {
-      if (formalFile.exists() && !tmpFile.exists()) {
-        // No need to recover
-        return;
-      }
-      if (!formalFile.exists() && !tmpFile.exists()) {
-        // First start
-        return;
-      }
-      if (formalFile.exists() && tmpFile.exists()) {
-        if (!tmpFile.delete()) {
-          LOGGER.warn(
-              "Delete system.properties tmp file fail, you may manually delete 
it: {}",
-              tmpFile.getAbsoluteFile());
-        }
-        return;
-      }
-      if (!formalFile.exists() && tmpFile.exists()) {
-        replaceFormalFile();
-        return;
-      }
+      recover();
+      // TODO: this line should be removed in 1.5
+      remove(IoTDBConstant.CLUSTER_NAME);
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
+  }
+
+  private void recover() throws IOException {
+    if (formalFile.exists() && !tmpFile.exists()) {
+      // No need to recover
+      return;
+    }
+    if (!formalFile.exists() && !tmpFile.exists()) {
+      // First start
+      return;
+    }
+    if (formalFile.exists() && tmpFile.exists()) {
+      if (!tmpFile.delete()) {
+        LOGGER.warn(
+            "Delete system.properties tmp file fail, you may manually delete 
it: {}",
+            tmpFile.getAbsoluteFile());
+      }
+      return;
+    }
+    if (!formalFile.exists() && tmpFile.exists()) {
+      replaceFormalFile();
+      return;
+    }
     throw new UnsupportedOperationException("Should never touch here");
   }
 
diff --git a/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift 
b/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
index 1ebfc0979a7..f218e004ede 100644
--- a/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
@@ -1340,7 +1340,10 @@ service IConfigNodeRPCService {
   /** Stop repair data task */
   common.TSStatus stopRepairData()
 
-  /** Load configuration on all DataNodes */
+  /** Submit configuration task to every datanodes */
+  common.TSStatus submitLoadConfigurationTask()
+
+  /** Load configuration on this confignode */
   common.TSStatus loadConfiguration()
 
   /** Set system status on DataNodes */

Reply via email to