• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #9965

30 Aug 2023 11:08AM UTC coverage: 47.773% (+0.01%) from 47.759%
#9965

push

travis_ci

web-flow
[IOTDB-6129] ConfigNode restarts without relying on Seed-ConfigNode  (#10988)

9 of 9 new or added lines in 2 files covered. (100.0%)

80390 of 168274 relevant lines covered (47.77%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.22
/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/conf/SystemPropertiesUtils.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.apache.iotdb.confignode.conf;
21

22
import org.apache.iotdb.common.rpc.thrift.TConfigNodeLocation;
23
import org.apache.iotdb.commons.conf.CommonConfig;
24
import org.apache.iotdb.commons.conf.CommonDescriptor;
25
import org.apache.iotdb.commons.conf.IoTDBConstant;
26
import org.apache.iotdb.commons.exception.BadNodeUrlException;
27
import org.apache.iotdb.commons.utils.NodeUrlUtils;
28

29
import org.slf4j.Logger;
30
import org.slf4j.LoggerFactory;
31

32
import java.io.File;
33
import java.io.FileInputStream;
34
import java.io.FileOutputStream;
35
import java.io.IOException;
36
import java.util.ArrayList;
37
import java.util.List;
38
import java.util.Objects;
39
import java.util.Properties;
40

41
import static org.apache.iotdb.commons.conf.IoTDBConstant.CLUSTER_NAME;
42
import static org.apache.iotdb.commons.conf.IoTDBConstant.DEFAULT_CLUSTER_NAME;
43

44
public class SystemPropertiesUtils {
45

46
  private static final Logger LOGGER = LoggerFactory.getLogger(SystemPropertiesUtils.class);
1✔
47

48
  private static final File systemPropertiesFile =
1✔
49
      new File(
50
          ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
1✔
51
              + File.separator
52
              + ConfigNodeConstant.SYSTEM_FILE_NAME);
53

54
  private static final ConfigNodeConfig conf = ConfigNodeDescriptor.getInstance().getConf();
1✔
55
  private static final CommonConfig COMMON_CONFIG = CommonDescriptor.getInstance().getConfig();
1✔
56

57
  private static final String CN_INTERNAL_ADDRESS = "cn_internal_address";
58
  private static final String CN_INTERNAL_PORT = "cn_internal_port";
59
  private static final String CN_CONSENSUS_PORT = "cn_consensus_port";
60
  private static final String CN_CONSENSUS_PROTOCOL = "config_node_consensus_protocol_class";
61
  private static final String DATA_CONSENSUS_PROTOCOL = "data_region_consensus_protocol_class";
62
  private static final String SCHEMA_CONSENSUS_PROTOCOL = "schema_region_consensus_protocol_class";
63
  private static final String SERIES_PARTITION_SLOT_NUM = "series_partition_slot_num";
64
  private static final String SERIES_PARTITION_EXECUTOR_CLASS = "series_partition_executor_class";
65
  private static final String TIME_PARTITION_INTERVAL = "time_partition_interval";
66

67
  private SystemPropertiesUtils() {
×
68
    throw new IllegalStateException("Utility class: SystemPropertiesUtils.");
×
69
  }
70

71
  /**
72
   * Check if the ConfigNode is restarted.
73
   *
74
   * @return True if confignode-system.properties file exist.
75
   */
76
  public static boolean isRestarted() {
77
    return systemPropertiesFile.exists();
×
78
  }
79

80
  /**
81
   * Check whether system parameters are consistent during each restart. We only invoke this
82
   * interface when restarted.
83
   *
84
   * @throws IOException When read the confignode-system.properties file failed
85
   */
86
  public static void checkSystemProperties() throws IOException {
87
    Properties systemProperties = getSystemProperties();
×
88
    boolean needReWrite = false;
×
89
    final String format =
×
90
        "[SystemProperties] The parameter \"{}\" can't be modified after first startup."
91
            + " Your configuration: {} will be forced update to: {}";
92

93
    // Cluster configuration
94
    String clusterName = systemProperties.getProperty(CLUSTER_NAME, null);
×
95
    if (clusterName == null) {
×
96
      needReWrite = true;
×
97
    } else if (!clusterName.equals(conf.getClusterName())) {
×
98
      LOGGER.warn(format, CLUSTER_NAME, conf.getClusterName(), clusterName);
×
99
      conf.setClusterName(clusterName);
×
100
    }
101

102
    String internalAddress = systemProperties.getProperty(CN_INTERNAL_ADDRESS, null);
×
103
    if (internalAddress == null) {
×
104
      needReWrite = true;
×
105
    } else if (!internalAddress.equals(conf.getInternalAddress())) {
×
106
      LOGGER.warn(format, CN_INTERNAL_ADDRESS, conf.getInternalAddress(), internalAddress);
×
107
      conf.setInternalAddress(internalAddress);
×
108
    }
109

110
    if (systemProperties.getProperty(CN_INTERNAL_PORT, null) == null) {
×
111
      needReWrite = true;
×
112
    } else {
113
      int internalPort = Integer.parseInt(systemProperties.getProperty(CN_INTERNAL_PORT));
×
114
      if (internalPort != conf.getInternalPort()) {
×
115
        LOGGER.warn(format, CN_INTERNAL_PORT, conf.getInternalPort(), internalPort);
×
116
        conf.setInternalPort(internalPort);
×
117
      }
118
    }
119

120
    if (systemProperties.getProperty(CN_CONSENSUS_PORT, null) == null) {
×
121
      needReWrite = true;
×
122
    } else {
123
      int consensusPort = Integer.parseInt(systemProperties.getProperty(CN_CONSENSUS_PORT));
×
124
      if (consensusPort != conf.getConsensusPort()) {
×
125
        LOGGER.warn(format, CN_CONSENSUS_PORT, conf.getConsensusPort(), consensusPort);
×
126
        conf.setConsensusPort(consensusPort);
×
127
      }
128
    }
129

130
    // Consensus protocol configuration
131
    String configNodeConsensusProtocolClass =
×
132
        systemProperties.getProperty(CN_CONSENSUS_PROTOCOL, null);
×
133
    if (configNodeConsensusProtocolClass == null) {
×
134
      needReWrite = true;
×
135
    } else if (!configNodeConsensusProtocolClass.equals(
×
136
        conf.getConfigNodeConsensusProtocolClass())) {
×
137
      LOGGER.warn(
×
138
          format,
139
          CN_CONSENSUS_PROTOCOL,
140
          conf.getConfigNodeConsensusProtocolClass(),
×
141
          configNodeConsensusProtocolClass);
142
      conf.setConfigNodeConsensusProtocolClass(configNodeConsensusProtocolClass);
×
143
    }
144

145
    String dataRegionConsensusProtocolClass =
×
146
        systemProperties.getProperty(DATA_CONSENSUS_PROTOCOL, null);
×
147
    if (dataRegionConsensusProtocolClass == null) {
×
148
      needReWrite = true;
×
149
    } else if (!dataRegionConsensusProtocolClass.equals(
×
150
        conf.getDataRegionConsensusProtocolClass())) {
×
151
      LOGGER.warn(
×
152
          format,
153
          DATA_CONSENSUS_PROTOCOL,
154
          conf.getDataRegionConsensusProtocolClass(),
×
155
          dataRegionConsensusProtocolClass);
156
      conf.setDataRegionConsensusProtocolClass(dataRegionConsensusProtocolClass);
×
157
    }
158

159
    String schemaRegionConsensusProtocolClass =
×
160
        systemProperties.getProperty(SCHEMA_CONSENSUS_PROTOCOL, null);
×
161
    if (schemaRegionConsensusProtocolClass == null) {
×
162
      needReWrite = true;
×
163
    } else if (!schemaRegionConsensusProtocolClass.equals(
×
164
        conf.getSchemaRegionConsensusProtocolClass())) {
×
165
      LOGGER.warn(
×
166
          format,
167
          SCHEMA_CONSENSUS_PROTOCOL,
168
          conf.getSchemaRegionConsensusProtocolClass(),
×
169
          schemaRegionConsensusProtocolClass);
170
      conf.setSchemaRegionConsensusProtocolClass(schemaRegionConsensusProtocolClass);
×
171
    }
172

173
    // PartitionSlot configuration
174
    if (systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM, null) == null) {
×
175
      needReWrite = true;
×
176
    } else {
177
      int seriesPartitionSlotNum =
×
178
          Integer.parseInt(systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM));
×
179
      if (seriesPartitionSlotNum != conf.getSeriesSlotNum()) {
×
180
        LOGGER.warn(format, "series_slot_num", conf.getSeriesSlotNum(), seriesPartitionSlotNum);
×
181
        conf.setSeriesSlotNum(seriesPartitionSlotNum);
×
182
      }
183
    }
184

185
    String seriesPartitionSlotExecutorClass =
×
186
        systemProperties.getProperty(SERIES_PARTITION_EXECUTOR_CLASS, null);
×
187
    if (seriesPartitionSlotExecutorClass == null) {
×
188
      needReWrite = true;
×
189
    } else if (!Objects.equals(
×
190
        seriesPartitionSlotExecutorClass, conf.getSeriesPartitionExecutorClass())) {
×
191
      LOGGER.warn(
×
192
          format,
193
          SERIES_PARTITION_EXECUTOR_CLASS,
194
          conf.getSeriesPartitionExecutorClass(),
×
195
          seriesPartitionSlotExecutorClass);
196
      conf.setSeriesPartitionExecutorClass(seriesPartitionSlotExecutorClass);
×
197
    }
198

199
    if (systemProperties.getProperty(TIME_PARTITION_INTERVAL, null) == null) {
×
200
      needReWrite = true;
×
201
    } else {
202
      long timePartitionInterval =
×
203
          Long.parseLong(systemProperties.getProperty(TIME_PARTITION_INTERVAL));
×
204
      if (timePartitionInterval != COMMON_CONFIG.getTimePartitionInterval()) {
×
205
        LOGGER.warn(
×
206
            format,
207
            TIME_PARTITION_INTERVAL,
208
            COMMON_CONFIG.getTimePartitionInterval(),
×
209
            timePartitionInterval);
×
210
        COMMON_CONFIG.setTimePartitionInterval(timePartitionInterval);
×
211
      }
212
    }
213

214
    if (needReWrite) {
×
215
      // Re-write special parameters if necessary
216
      storeSystemParameters();
×
217
    }
218
  }
×
219

220
  /**
221
   * Load the config_node_list in confignode-system.properties file. We only invoke this interface
222
   * when restarted.
223
   *
224
   * @return The property of config_node_list in confignode-system.properties file
225
   * @throws IOException When load confignode-system.properties file failed
226
   * @throws BadNodeUrlException When parsing config_node_list failed
227
   */
228
  public static List<TConfigNodeLocation> loadConfigNodeList()
229
      throws IOException, BadNodeUrlException {
230
    Properties systemProperties = getSystemProperties();
×
231
    String addresses = systemProperties.getProperty("config_node_list", null);
×
232

233
    if (addresses != null && !addresses.isEmpty()) {
×
234
      return NodeUrlUtils.parseTConfigNodeUrls(addresses);
×
235
    } else {
236
      return new ArrayList<>();
×
237
    }
238
  }
239

240
  /**
241
   * The system parameters can't be changed after the ConfigNode first started. Therefore, store
242
   * them in confignode-system.properties during the first startup.
243
   *
244
   * @throws IOException getSystemProperties()
245
   */
246
  public static void storeSystemParameters() throws IOException {
247
    Properties systemProperties = getSystemProperties();
×
248

249
    systemProperties.setProperty("iotdb_version", IoTDBConstant.VERSION);
×
250
    systemProperties.setProperty("commit_id", IoTDBConstant.BUILD_INFO);
×
251

252
    // Cluster configuration
253
    systemProperties.setProperty("cluster_name", conf.getClusterName());
×
254
    LOGGER.info("[SystemProperties] store cluster_name: {}", conf.getClusterName());
×
255
    systemProperties.setProperty("config_node_id", String.valueOf(conf.getConfigNodeId()));
×
256
    LOGGER.info("[SystemProperties] store config_node_id: {}", conf.getConfigNodeId());
×
257
    systemProperties.setProperty(
×
258
        "is_seed_config_node",
259
        String.valueOf(ConfigNodeDescriptor.getInstance().isSeedConfigNode()));
×
260
    LOGGER.info(
×
261
        "[SystemProperties] store is_seed_config_node: {}",
262
        ConfigNodeDescriptor.getInstance().isSeedConfigNode());
×
263

264
    // Startup configuration
265
    systemProperties.setProperty(CN_INTERNAL_ADDRESS, String.valueOf(conf.getInternalAddress()));
×
266
    systemProperties.setProperty(CN_INTERNAL_PORT, String.valueOf(conf.getInternalPort()));
×
267
    systemProperties.setProperty(CN_CONSENSUS_PORT, String.valueOf(conf.getConsensusPort()));
×
268

269
    // Consensus protocol configuration
270
    systemProperties.setProperty(CN_CONSENSUS_PROTOCOL, conf.getConfigNodeConsensusProtocolClass());
×
271
    systemProperties.setProperty(
×
272
        DATA_CONSENSUS_PROTOCOL, conf.getDataRegionConsensusProtocolClass());
×
273
    systemProperties.setProperty(
×
274
        SCHEMA_CONSENSUS_PROTOCOL, conf.getSchemaRegionConsensusProtocolClass());
×
275

276
    // PartitionSlot configuration
277
    systemProperties.setProperty(
×
278
        SERIES_PARTITION_SLOT_NUM, String.valueOf(conf.getSeriesSlotNum()));
×
279
    systemProperties.setProperty(
×
280
        SERIES_PARTITION_EXECUTOR_CLASS, conf.getSeriesPartitionExecutorClass());
×
281
    systemProperties.setProperty(
×
282
        TIME_PARTITION_INTERVAL, String.valueOf(COMMON_CONFIG.getTimePartitionInterval()));
×
283
    systemProperties.setProperty("timestamp_precision", COMMON_CONFIG.getTimestampPrecision());
×
284

285
    // DataNode Functions
286
    systemProperties.setProperty("schema_engine_mode", COMMON_CONFIG.getSchemaEngineMode());
×
287
    systemProperties.setProperty(
×
288
        "tag_attribute_total_size", String.valueOf(COMMON_CONFIG.getTagAttributeTotalSize()));
×
289

290
    storeSystemProperties(systemProperties);
×
291
  }
×
292

293
  /**
294
   * Store the latest config_node_list in confignode-system.properties file
295
   *
296
   * @param configNodes The latest ConfigNodeList
297
   * @throws IOException When store confignode-system.properties file failed
298
   */
299
  public static void storeConfigNodeList(List<TConfigNodeLocation> configNodes) throws IOException {
300
    if (!systemPropertiesFile.exists()) {
1✔
301
      // Avoid creating confignode-system.properties files during
302
      // synchronizing the ApplyConfigNode logs from the ConsensusLayer.
303
      // 1. For the Non-Seed-ConfigNode, We don't need to create confignode-system.properties file
304
      // until the leader sends the notifyRegisterSuccess request.
305
      // 2. The leader commits the ApplyConfigNode log at the end of AddConfigNodeProcedure,
306
      // in which case the latest config_node_list will be updated.
307
      return;
1✔
308
    }
309

310
    Properties systemProperties = getSystemProperties();
×
311
    systemProperties.setProperty(
×
312
        "config_node_list", NodeUrlUtils.convertTConfigNodeUrls(configNodes));
×
313

314
    storeSystemProperties(systemProperties);
×
315
  }
×
316

317
  /**
318
   * Load the cluster_name in confignode-system.properties file. We only invoke this interface when
319
   * restarted.
320
   *
321
   * @return The property of cluster_name in confignode-system.properties file
322
   * @throws IOException When load confignode-system.properties file failed
323
   */
324
  public static String loadClusterNameWhenRestarted() throws IOException {
325
    Properties systemProperties = getSystemProperties();
×
326
    String clusterName = systemProperties.getProperty(CLUSTER_NAME, null);
×
327
    if (clusterName == null) {
×
328
      LOGGER.warn(
×
329
          "Lack cluster_name field in "
330
              + "data/confignode/system/confignode-system.properties, set it as defaultCluster");
331
      systemProperties.setProperty(CLUSTER_NAME, DEFAULT_CLUSTER_NAME);
×
332
      return systemProperties.getProperty(CLUSTER_NAME, null);
×
333
    }
334
    return clusterName;
×
335
  }
336

337
  /**
338
   * Load the config_node_id in confignode-system.properties file. We only invoke this interface
339
   * when restarted.
340
   *
341
   * @return The property of config_node_id in confignode-system.properties file
342
   * @throws IOException When load confignode-system.properties file failed
343
   */
344
  public static int loadConfigNodeIdWhenRestarted() throws IOException {
345
    Properties systemProperties = getSystemProperties();
×
346
    try {
347
      return Integer.parseInt(systemProperties.getProperty("config_node_id", null));
×
348
    } catch (NumberFormatException e) {
×
349
      throw new IOException(
×
350
          "The parameter config_node_id doesn't exist in "
351
              + "data/confignode/system/confignode-system.properties. "
352
              + "Please delete data dir data/confignode and restart again.");
353
    }
354
  }
355

356
  /**
357
   * Check if the current ConfigNode is SeedConfigNode.
358
   *
359
   * <p>Notice: Only invoke this interface when restarted.
360
   *
361
   * @return True if the is_seed_config_node is set to True in iotdb-confignode.properties file
362
   */
363
  public static boolean isSeedConfigNode() {
364
    try {
365
      Properties systemProperties = getSystemProperties();
×
366
      boolean isSeedConfigNode =
×
367
          Boolean.parseBoolean(systemProperties.getProperty("is_seed_config_node", null));
×
368
      if (isSeedConfigNode) {
×
369
        return true;
×
370
      } else {
371
        return ConfigNodeDescriptor.getInstance().isSeedConfigNode();
×
372
      }
373
    } catch (IOException ignore) {
×
374
      return false;
×
375
    }
376
  }
377

378
  private static synchronized Properties getSystemProperties() throws IOException {
379
    // Create confignode-system.properties file if necessary
380
    if (!systemPropertiesFile.exists()) {
×
381
      if (systemPropertiesFile.createNewFile()) {
×
382
        LOGGER.info(
×
383
            "System properties file {} for ConfigNode is created.",
384
            systemPropertiesFile.getAbsolutePath());
×
385
      } else {
386
        LOGGER.error(
×
387
            "Can't create the system properties file {} for ConfigNode. "
388
                + "IoTDB-ConfigNode is shutdown.",
389
            systemPropertiesFile.getAbsolutePath());
×
390
        throw new IOException("Can't create system properties file");
×
391
      }
392
    }
393

394
    Properties systemProperties = new Properties();
×
395
    try (FileInputStream inputStream = new FileInputStream(systemPropertiesFile)) {
×
396
      systemProperties.load(inputStream);
×
397
    }
398
    return systemProperties;
×
399
  }
400

401
  private static synchronized void storeSystemProperties(Properties systemProperties)
402
      throws IOException {
403
    try (FileOutputStream fileOutputStream = new FileOutputStream(systemPropertiesFile)) {
×
404
      systemProperties.store(
×
405
          fileOutputStream,
406
          " THIS FILE IS AUTOMATICALLY GENERATED. PLEASE DO NOT MODIFY THIS FILE !!!");
407
    }
408
  }
×
409
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc