blob: abff0282398c7fe4564c882d8ed79cf7466797ae [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.exception.BadNodeUrlException;
import org.apache.iotdb.commons.exception.ConfigurationException;
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.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
public class SystemPropertiesUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SystemPropertiesUtils.class);
private static final File systemPropertiesFile =
new File(
ConfigNodeDescriptor.getInstance().getConf().getSystemDir()
+ File.separator
+ ConfigNodeConstant.SYSTEM_FILE_NAME);
private static final ConfigNodeConfig conf = ConfigNodeDescriptor.getInstance().getConf();
/**
* 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
* @throws ConfigurationException When some system parameters are inconsistent
*/
public static void checkSystemProperties() throws IOException, ConfigurationException {
Properties systemProperties = getSystemProperties();
boolean needReWrite = false;
// Startup configuration
String internalAddress = systemProperties.getProperty("internal_address", null);
if (internalAddress == null) {
needReWrite = true;
} else if (!internalAddress.equals(conf.getInternalAddress())) {
throw new ConfigurationException(
"internal_address", conf.getInternalAddress(), internalAddress);
}
if (systemProperties.getProperty("internal_port", null) == null) {
needReWrite = true;
} else {
int internalPort = Integer.parseInt(systemProperties.getProperty("internal_port"));
if (internalPort != conf.getInternalPort()) {
throw new ConfigurationException(
"internal_port", String.valueOf(conf.getInternalPort()), String.valueOf(internalPort));
}
}
if (systemProperties.getProperty("consensus_port", null) == null) {
needReWrite = true;
} else {
int consensusPort = Integer.parseInt(systemProperties.getProperty("consensus_port"));
if (consensusPort != conf.getConsensusPort()) {
throw new ConfigurationException(
"consensus_port",
String.valueOf(conf.getConsensusPort()),
String.valueOf(consensusPort));
}
}
// Consensus protocol configuration
String configNodeConsensusProtocolClass =
systemProperties.getProperty("config_node_consensus_protocol_class", null);
if (configNodeConsensusProtocolClass == null) {
needReWrite = true;
} else if (!configNodeConsensusProtocolClass.equals(
conf.getConfigNodeConsensusProtocolClass())) {
throw new ConfigurationException(
"config_node_consensus_protocol_class",
conf.getConfigNodeConsensusProtocolClass(),
configNodeConsensusProtocolClass);
}
String dataRegionConsensusProtocolClass =
systemProperties.getProperty("data_region_consensus_protocol_class", null);
if (dataRegionConsensusProtocolClass == null) {
needReWrite = true;
} else if (!dataRegionConsensusProtocolClass.equals(
conf.getDataRegionConsensusProtocolClass())) {
throw new ConfigurationException(
"data_region_consensus_protocol_class",
conf.getDataRegionConsensusProtocolClass(),
dataRegionConsensusProtocolClass);
}
String schemaRegionConsensusProtocolClass =
systemProperties.getProperty("schema_region_consensus_protocol_class", null);
if (schemaRegionConsensusProtocolClass == null) {
needReWrite = true;
} else if (!schemaRegionConsensusProtocolClass.equals(
conf.getSchemaRegionConsensusProtocolClass())) {
throw new ConfigurationException(
"schema_region_consensus_protocol_class",
conf.getSchemaRegionConsensusProtocolClass(),
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.getSeriesPartitionSlotNum()) {
throw new ConfigurationException(
"series_partition_slot_num",
String.valueOf(conf.getSeriesPartitionSlotNum()),
String.valueOf(seriesPartitionSlotNum));
}
}
String seriesPartitionSlotExecutorClass =
systemProperties.getProperty("series_partition_executor_class", null);
if (seriesPartitionSlotExecutorClass == null) {
needReWrite = true;
} else if (!Objects.equals(
seriesPartitionSlotExecutorClass, conf.getSeriesPartitionExecutorClass())) {
throw new ConfigurationException(
"series_partition_executor_class",
conf.getSeriesPartitionExecutorClass(),
seriesPartitionSlotExecutorClass);
}
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
*/
public static void storeSystemParameters() throws IOException {
Properties systemProperties = getSystemProperties();
// Startup configuration
systemProperties.setProperty("internal_address", String.valueOf(conf.getInternalAddress()));
systemProperties.setProperty("internal_port", String.valueOf(conf.getInternalPort()));
systemProperties.setProperty("consensus_port", String.valueOf(conf.getConsensusPort()));
// Consensus protocol configuration
systemProperties.setProperty(
"config_node_consensus_protocol_class", conf.getConfigNodeConsensusProtocolClass());
systemProperties.setProperty(
"data_region_consensus_protocol_class", conf.getDataRegionConsensusProtocolClass());
systemProperties.setProperty(
"schema_region_consensus_protocol_class", conf.getSchemaRegionConsensusProtocolClass());
// PartitionSlot configuration
systemProperties.setProperty(
"series_partition_slot_num", String.valueOf(conf.getSeriesPartitionSlotNum()));
systemProperties.setProperty(
"series_partition_executor_class", conf.getSeriesPartitionExecutorClass());
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);
}
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(inputStream);
}
return systemProperties;
}
private static synchronized void storeSystemProperties(Properties systemProperties)
throws IOException {
try (FileOutputStream fileOutputStream = new FileOutputStream(systemPropertiesFile)) {
systemProperties.store(fileOutputStream, "");
}
}
}