blob: ba9d74a641cd4a3fa0117c748da53acddde47621 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.iotdb.confignode.conf;
import org.apache.iotdb.common.rpc.thrift.TConfigNodeLocation;
import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.exception.BadNodeUrlException;
import org.apache.iotdb.commons.utils.NodeUrlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
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 File systemPropertiesFile =
new File(
ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
+ File.separator
+ ConfigNodeConstant.SYSTEM_FILE_NAME);
private static final ConfigNodeConfig conf = ConfigNodeDescriptor.getInstance().getConf();
private static final CommonConfig COMMON_CONFIG = CommonDescriptor.getInstance().getConfig();
private static final String CN_INTERNAL_ADDRESS = "cn_internal_address";
private static final String CN_INTERNAL_PORT = "cn_internal_port";
private static final String CN_CONSENSUS_PORT = "cn_consensus_port";
private static final String TIMESTAMP_PRECISION = "timestamp_precision";
private static final String CN_CONSENSUS_PROTOCOL = "config_node_consensus_protocol_class";
private static final String DATA_CONSENSUS_PROTOCOL = "data_region_consensus_protocol_class";
private static final String SCHEMA_CONSENSUS_PROTOCOL = "schema_region_consensus_protocol_class";
private static final String SERIES_PARTITION_SLOT_NUM = "series_partition_slot_num";
private static final String SERIES_PARTITION_EXECUTOR_CLASS = "series_partition_executor_class";
private static final String TIME_PARTITION_INTERVAL = "time_partition_interval";
private SystemPropertiesUtils() {
throw new IllegalStateException("Utility class: SystemPropertiesUtils.");
}
// TODO: This needs removal of statics ...
public static void reinitializeStatics() {
systemPropertiesFile =
new File(
ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
+ File.separator
+ ConfigNodeConstant.SYSTEM_FILE_NAME);
}
/**
* Check if the ConfigNode is restarted.
*
* @return True if confignode-system.properties file exist.
*/
public static boolean isRestarted() {
return systemPropertiesFile.exists();
}
/**
* Check whether system parameters are consistent during each restart. We only invoke this
* interface when restarted.
*
* @throws IOException When read the confignode-system.properties file failed
*/
public static void checkSystemProperties() throws IOException {
Properties systemProperties = getSystemProperties();
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())) {
LOGGER.warn(format, CN_INTERNAL_ADDRESS, conf.getInternalAddress(), internalAddress);
conf.setInternalAddress(internalAddress);
}
if (systemProperties.getProperty(CN_INTERNAL_PORT, null) == null) {
needReWrite = true;
} else {
int internalPort = Integer.parseInt(systemProperties.getProperty(CN_INTERNAL_PORT));
if (internalPort != conf.getInternalPort()) {
LOGGER.warn(format, CN_INTERNAL_PORT, conf.getInternalPort(), internalPort);
conf.setInternalPort(internalPort);
}
}
if (systemProperties.getProperty(CN_CONSENSUS_PORT, null) == null) {
needReWrite = true;
} else {
int consensusPort = Integer.parseInt(systemProperties.getProperty(CN_CONSENSUS_PORT));
if (consensusPort != conf.getConsensusPort()) {
LOGGER.warn(format, CN_CONSENSUS_PORT, conf.getConsensusPort(), consensusPort);
conf.setConsensusPort(consensusPort);
}
}
if (systemProperties.getProperty(TIMESTAMP_PRECISION, null) == null) {
needReWrite = true;
} else {
String timestampPrecision = systemProperties.getProperty(TIMESTAMP_PRECISION);
if (!timestampPrecision.equals(COMMON_CONFIG.getTimestampPrecision())) {
LOGGER.warn(
format, TIMESTAMP_PRECISION, COMMON_CONFIG.getTimestampPrecision(), timestampPrecision);
COMMON_CONFIG.setTimestampPrecision(timestampPrecision);
}
}
// Consensus protocol configuration
String configNodeConsensusProtocolClass =
systemProperties.getProperty(CN_CONSENSUS_PROTOCOL, null);
if (configNodeConsensusProtocolClass == null) {
needReWrite = true;
} else if (!configNodeConsensusProtocolClass.equals(
conf.getConfigNodeConsensusProtocolClass())) {
LOGGER.warn(
format,
CN_CONSENSUS_PROTOCOL,
conf.getConfigNodeConsensusProtocolClass(),
configNodeConsensusProtocolClass);
conf.setConfigNodeConsensusProtocolClass(configNodeConsensusProtocolClass);
}
String dataRegionConsensusProtocolClass =
systemProperties.getProperty(DATA_CONSENSUS_PROTOCOL, null);
if (dataRegionConsensusProtocolClass == null) {
needReWrite = true;
} else if (!dataRegionConsensusProtocolClass.equals(
conf.getDataRegionConsensusProtocolClass())) {
LOGGER.warn(
format,
DATA_CONSENSUS_PROTOCOL,
conf.getDataRegionConsensusProtocolClass(),
dataRegionConsensusProtocolClass);
conf.setDataRegionConsensusProtocolClass(dataRegionConsensusProtocolClass);
}
String schemaRegionConsensusProtocolClass =
systemProperties.getProperty(SCHEMA_CONSENSUS_PROTOCOL, null);
if (schemaRegionConsensusProtocolClass == null) {
needReWrite = true;
} else if (!schemaRegionConsensusProtocolClass.equals(
conf.getSchemaRegionConsensusProtocolClass())) {
LOGGER.warn(
format,
SCHEMA_CONSENSUS_PROTOCOL,
conf.getSchemaRegionConsensusProtocolClass(),
schemaRegionConsensusProtocolClass);
conf.setSchemaRegionConsensusProtocolClass(schemaRegionConsensusProtocolClass);
}
// PartitionSlot configuration
if (systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM, null) == null) {
needReWrite = true;
} else {
int seriesPartitionSlotNum =
Integer.parseInt(systemProperties.getProperty(SERIES_PARTITION_SLOT_NUM));
if (seriesPartitionSlotNum != conf.getSeriesSlotNum()) {
LOGGER.warn(format, "series_slot_num", conf.getSeriesSlotNum(), seriesPartitionSlotNum);
conf.setSeriesSlotNum(seriesPartitionSlotNum);
}
}
String seriesPartitionSlotExecutorClass =
systemProperties.getProperty(SERIES_PARTITION_EXECUTOR_CLASS, null);
if (seriesPartitionSlotExecutorClass == null) {
needReWrite = true;
} else if (!Objects.equals(
seriesPartitionSlotExecutorClass, conf.getSeriesPartitionExecutorClass())) {
LOGGER.warn(
format,
SERIES_PARTITION_EXECUTOR_CLASS,
conf.getSeriesPartitionExecutorClass(),
seriesPartitionSlotExecutorClass);
conf.setSeriesPartitionExecutorClass(seriesPartitionSlotExecutorClass);
}
if (systemProperties.getProperty(TIME_PARTITION_INTERVAL, null) == null) {
needReWrite = true;
} else {
long timePartitionInterval =
Long.parseLong(systemProperties.getProperty(TIME_PARTITION_INTERVAL));
if (timePartitionInterval != COMMON_CONFIG.getTimePartitionInterval()) {
LOGGER.warn(
format,
TIME_PARTITION_INTERVAL,
COMMON_CONFIG.getTimePartitionInterval(),
timePartitionInterval);
COMMON_CONFIG.setTimePartitionInterval(timePartitionInterval);
}
}
if (needReWrite) {
// Re-write special parameters if necessary
storeSystemParameters();
}
}
/**
* Load the config_node_list in confignode-system.properties file. We only invoke this interface
* when restarted.
*
* @return The property of config_node_list in confignode-system.properties file
* @throws IOException When load confignode-system.properties file failed
* @throws BadNodeUrlException When parsing config_node_list failed
*/
public static List<TConfigNodeLocation> loadConfigNodeList()
throws IOException, BadNodeUrlException {
Properties systemProperties = getSystemProperties();
String addresses = systemProperties.getProperty("config_node_list", null);
if (addresses != null && !addresses.isEmpty()) {
return NodeUrlUtils.parseTConfigNodeUrls(addresses);
} else {
return new ArrayList<>();
}
}
/**
* The system parameters can't be changed after the ConfigNode first started. Therefore, store
* them in confignode-system.properties during the first startup.
*
* @throws IOException getSystemProperties()
*/
public static void storeSystemParameters() throws IOException {
Properties systemProperties = getSystemProperties();
systemProperties.setProperty("iotdb_version", IoTDBConstant.VERSION);
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(
"is_seed_config_node",
String.valueOf(ConfigNodeDescriptor.getInstance().isSeedConfigNode()));
LOGGER.info(
"[SystemProperties] store is_seed_config_node: {}",
ConfigNodeDescriptor.getInstance().isSeedConfigNode());
// Startup configuration
systemProperties.setProperty(CN_INTERNAL_ADDRESS, String.valueOf(conf.getInternalAddress()));
systemProperties.setProperty(CN_INTERNAL_PORT, String.valueOf(conf.getInternalPort()));
systemProperties.setProperty(CN_CONSENSUS_PORT, String.valueOf(conf.getConsensusPort()));
// Consensus protocol configuration
systemProperties.setProperty(CN_CONSENSUS_PROTOCOL, conf.getConfigNodeConsensusProtocolClass());
systemProperties.setProperty(
DATA_CONSENSUS_PROTOCOL, conf.getDataRegionConsensusProtocolClass());
systemProperties.setProperty(
SCHEMA_CONSENSUS_PROTOCOL, conf.getSchemaRegionConsensusProtocolClass());
// PartitionSlot configuration
systemProperties.setProperty(
SERIES_PARTITION_SLOT_NUM, String.valueOf(conf.getSeriesSlotNum()));
systemProperties.setProperty(
SERIES_PARTITION_EXECUTOR_CLASS, conf.getSeriesPartitionExecutorClass());
systemProperties.setProperty(
TIME_PARTITION_INTERVAL, String.valueOf(COMMON_CONFIG.getTimePartitionInterval()));
systemProperties.setProperty(TIMESTAMP_PRECISION, COMMON_CONFIG.getTimestampPrecision());
// DataNode Functions
systemProperties.setProperty("schema_engine_mode", COMMON_CONFIG.getSchemaEngineMode());
systemProperties.setProperty(
"tag_attribute_total_size", String.valueOf(COMMON_CONFIG.getTagAttributeTotalSize()));
storeSystemProperties(systemProperties);
}
/**
* Store the latest config_node_list in confignode-system.properties file
*
* @param configNodes The latest ConfigNodeList
* @throws IOException When store confignode-system.properties file failed
*/
public static void storeConfigNodeList(List<TConfigNodeLocation> configNodes) throws IOException {
if (!systemPropertiesFile.exists()) {
// Avoid creating confignode-system.properties files during
// synchronizing the ApplyConfigNode logs from the ConsensusLayer.
// 1. For the Non-Seed-ConfigNode, We don't need to create confignode-system.properties file
// until the leader sends the notifyRegisterSuccess request.
// 2. The leader commits the ApplyConfigNode log at the end of AddConfigNodeProcedure,
// in which case the latest config_node_list will be updated.
return;
}
Properties systemProperties = getSystemProperties();
systemProperties.setProperty(
"config_node_list", NodeUrlUtils.convertTConfigNodeUrls(configNodes));
storeSystemProperties(systemProperties);
}
/**
* 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 = getSystemProperties();
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.
*
* @return The property of config_node_id in confignode-system.properties file
* @throws IOException When load confignode-system.properties file failed
*/
public static int loadConfigNodeIdWhenRestarted() throws IOException {
Properties systemProperties = getSystemProperties();
try {
return Integer.parseInt(systemProperties.getProperty("config_node_id", null));
} catch (NumberFormatException e) {
throw new IOException(
"The parameter config_node_id doesn't exist in "
+ "data/confignode/system/confignode-system.properties. "
+ "Please delete data dir data/confignode and restart again.",
e);
}
}
/**
* Check if the current ConfigNode is SeedConfigNode.
*
* <p>Notice: Only invoke this interface when restarted.
*
* @return True if the is_seed_config_node is set to True in iotdb-confignode.properties file
*/
public static boolean isSeedConfigNode() {
try {
Properties systemProperties = getSystemProperties();
boolean isSeedConfigNode =
Boolean.parseBoolean(systemProperties.getProperty("is_seed_config_node", null));
if (isSeedConfigNode) {
return true;
} else {
return ConfigNodeDescriptor.getInstance().isSeedConfigNode();
}
} catch (IOException ignore) {
return false;
}
}
private static synchronized Properties getSystemProperties() throws IOException {
// Create confignode-system.properties file if necessary
if (!systemPropertiesFile.exists()) {
if (systemPropertiesFile.createNewFile()) {
LOGGER.info(
"System properties file {} for ConfigNode is created.",
systemPropertiesFile.getAbsolutePath());
} else {
LOGGER.error(
"Can't create the system properties file {} for ConfigNode. "
+ "IoTDB-ConfigNode is shutdown.",
systemPropertiesFile.getAbsolutePath());
throw new IOException("Can't create system properties file");
}
}
Properties systemProperties = new Properties();
try (FileInputStream inputStream = new FileInputStream(systemPropertiesFile)) {
systemProperties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
}
return systemProperties;
}
private static synchronized void storeSystemProperties(Properties systemProperties)
throws IOException {
try (FileOutputStream fileOutputStream = new FileOutputStream(systemPropertiesFile)) {
systemProperties.store(
new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8),
" THIS FILE IS AUTOMATICALLY GENERATED. PLEASE DO NOT MODIFY THIS FILE !!!");
fileOutputStream.getFD().sync();
}
}
}