This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/dev/1.3 by this push:
new ffaf1d2e44d [to dev/1.3] apply new configurations in memory before
update file (#14501)
ffaf1d2e44d is described below
commit ffaf1d2e44ddc8b7864c3c0609e0aef0ecb21b8d
Author: shuwenwei <[email protected]>
AuthorDate: Fri Dec 20 14:52:48 2024 +0800
[to dev/1.3] apply new configurations in memory before update file (#14501)
* apply new configurations in memory before update file
* fix spell
* modify some Properties usages to TrimProperties
* Add TrimProperties to trim properties auto (#14289)
* Add TrimProperties to trim properties auto
* add license
* fix compile
---------
Co-authored-by: Yukim1 <[email protected]>
---
.../iotdb/db/it/IoTDBSetConfigurationIT.java | 10 +-
iotdb-core/confignode/pom.xml | 6 ++
.../confignode/conf/ConfigNodeDescriptor.java | 18 ++--
.../iotdb/confignode/manager/ConfigManager.java | 12 ++-
.../confignode/conf/ConfigNodePropertiesTest.java | 50 ++++++++++
iotdb-core/datanode/pom.xml | 6 ++
.../org/apache/iotdb/db/conf/IoTDBDescriptor.java | 85 ++++++++--------
.../db/conf/rest/IoTDBRestServiceDescriptor.java | 18 ++--
.../iotdb/db/storageengine/StorageEngine.java | 29 +++---
.../org/apache/iotdb/db/conf/PropertiesTest.java | 107 +++++++++++++++++++++
.../metrics/config/MetricConfigDescriptor.java | 6 +-
.../iotdb/commons/conf/CommonDescriptor.java | 11 +--
.../iotdb/commons/conf/ConfigurationFileUtils.java | 22 ++++-
.../apache/iotdb/commons/conf/TrimProperties.java | 50 ++++++++++
14 files changed, 347 insertions(+), 83 deletions(-)
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 fa8a450d675..8a792aacc38 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
@@ -169,7 +169,7 @@ public class IoTDBSetConfigurationIT {
// Modify the config file manually because the datanode can not restart
Properties properties = new Properties();
properties.put("cluster_name", "xx");
- ConfigurationFileUtils.updateConfigurationFile(getConfigFile(datanode),
properties);
+ ConfigurationFileUtils.updateConfiguration(getConfigFile(datanode),
properties, null);
EnvFactory.getEnv().getDataNodeWrapper(0).stop();
EnvFactory.getEnv().getDataNodeWrapper(0).start();
// wait the datanode restart successfully (won't do any meaningful
modification)
@@ -235,6 +235,14 @@ public class IoTDBSetConfigurationIT {
} catch (SQLException e) {
assertTrue(e.getMessage().contains("Illegal defaultStorageGroupLevel:
-1, should >= 1"));
}
+
+ // Failed updates will not change the files.
+ assertFalse(
+ checkConfigFileContains(
+ EnvFactory.getEnv().getDataNodeWrapper(0),
"default_storage_group_level=-1"));
+ assertTrue(
+ checkConfigFileContains(
+ EnvFactory.getEnv().getDataNodeWrapper(0),
"default_storage_group_level=3"));
}
// can start with an illegal value
diff --git a/iotdb-core/confignode/pom.xml b/iotdb-core/confignode/pom.xml
index 8d480477080..dd30ea1becd 100644
--- a/iotdb-core/confignode/pom.xml
+++ b/iotdb-core/confignode/pom.xml
@@ -154,6 +154,12 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.tngtech.archunit</groupId>
+ <artifactId>archunit</artifactId>
+ <version>1.3.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
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 77190535876..918c1856a00 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
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.ConfigurationFileUtils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.conf.TrimProperties;
import org.apache.iotdb.commons.exception.BadNodeUrlException;
import org.apache.iotdb.commons.schema.SchemaConstant;
import org.apache.iotdb.commons.utils.NodeUrlUtils;
@@ -46,7 +47,6 @@ import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Optional;
-import java.util.Properties;
public class ConfigNodeDescriptor {
private static final Logger LOGGER =
LoggerFactory.getLogger(ConfigNodeDescriptor.class);
@@ -118,13 +118,13 @@ public class ConfigNodeDescriptor {
}
private void loadProps() {
- Properties commonProperties = new Properties();
+ TrimProperties trimProperties = new TrimProperties();
URL url = getPropsUrl(CommonConfig.SYSTEM_CONFIG_NAME);
if (url != null) {
try (InputStream inputStream = url.openStream()) {
LOGGER.info("start reading ConfigNode conf file: {}", url);
- commonProperties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
- loadProperties(commonProperties);
+ trimProperties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
+ loadProperties(trimProperties);
} catch (IOException | BadNodeUrlException e) {
LOGGER.error("Couldn't load ConfigNode conf file, reject ConfigNode
startup.", e);
System.exit(-1);
@@ -133,7 +133,7 @@ public class ConfigNodeDescriptor {
commonDescriptor
.getConfig()
.updatePath(System.getProperty(ConfigNodeConstant.CONFIGNODE_HOME,
null));
- MetricConfigDescriptor.getInstance().loadProps(commonProperties, true);
+ MetricConfigDescriptor.getInstance().loadProps(trimProperties, true);
MetricConfigDescriptor.getInstance()
.getMetricConfig()
.updateRpcInstance(NodeType.CONFIGNODE,
SchemaConstant.SYSTEM_DATABASE);
@@ -145,7 +145,7 @@ public class ConfigNodeDescriptor {
}
}
- private void loadProperties(Properties properties) throws
BadNodeUrlException, IOException {
+ private void loadProperties(TrimProperties properties) throws
BadNodeUrlException, IOException {
conf.setClusterName(
properties.getProperty(IoTDBConstant.CLUSTER_NAME,
conf.getClusterName()).trim());
@@ -401,7 +401,7 @@ public class ConfigNodeDescriptor {
loadCQConfig(properties);
}
- private void loadRatisConsensusConfig(Properties properties) {
+ private void loadRatisConsensusConfig(TrimProperties properties) {
conf.setDataRegionRatisConsensusLogAppenderBufferSize(
Long.parseLong(
properties
@@ -813,7 +813,7 @@ public class ConfigNodeDescriptor {
.trim()));
}
- private void loadCQConfig(Properties properties) {
+ private void loadCQConfig(TrimProperties properties) {
int cqSubmitThread =
Integer.parseInt(
properties
@@ -871,7 +871,7 @@ public class ConfigNodeDescriptor {
}
}
- public void loadHotModifiedProps(Properties properties) {
+ public void loadHotModifiedProps(TrimProperties properties) {
Optional.ofNullable(properties.getProperty(IoTDBConstant.CLUSTER_NAME))
.ifPresent(conf::setClusterName);
}
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 71c5746ba6c..87ceac0acac 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
@@ -42,6 +42,7 @@ import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.ConfigurationFileUtils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.conf.TrimProperties;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.path.PartialPath;
@@ -244,7 +245,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -1582,13 +1582,18 @@ public class ConfigManager implements IManager {
if (currentNodeId == req.getNodeId() || req.getNodeId() < 0) {
URL url =
ConfigNodeDescriptor.getPropsUrl(CommonConfig.SYSTEM_CONFIG_NAME);
boolean configurationFileFound = (url != null && new
File(url.getFile()).exists());
- Properties properties = new Properties();
+ TrimProperties properties = new TrimProperties();
properties.putAll(req.getConfigs());
if (configurationFileFound) {
File file = new File(url.getFile());
try {
- ConfigurationFileUtils.updateConfigurationFile(file, properties);
+ ConfigurationFileUtils.updateConfiguration(
+ file,
+ properties,
+ mergedProps -> {
+
ConfigNodeDescriptor.getInstance().loadHotModifiedProps(mergedProps);
+ });
} catch (Exception e) {
tsStatus = RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR,
e.getMessage());
}
@@ -1598,7 +1603,6 @@ public class ConfigManager implements IManager {
tsStatus = RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR,
msg);
LOGGER.warn(msg);
}
- ConfigNodeDescriptor.getInstance().loadHotModifiedProps(properties);
if (currentNodeId == req.getNodeId()) {
return tsStatus;
}
diff --git
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/conf/ConfigNodePropertiesTest.java
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/conf/ConfigNodePropertiesTest.java
new file mode 100644
index 00000000000..1101fcc3f11
--- /dev/null
+++
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/conf/ConfigNodePropertiesTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.tngtech.archunit.core.domain.JavaClasses;
+import com.tngtech.archunit.core.importer.ClassFileImporter;
+import com.tngtech.archunit.core.importer.ImportOption;
+import com.tngtech.archunit.lang.ArchRule;
+import org.junit.Test;
+
+import java.util.Properties;
+
+import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
+
+public class ConfigNodePropertiesTest {
+ @Test
+ public void TrimPropertiesOnly() {
+ JavaClasses allClasses =
+ new ClassFileImporter()
+ .withImportOption(new ImportOption.DoNotIncludeTests())
+ .importPackages("org.apache.iotdb");
+
+ ArchRule rule =
+ noClasses()
+ .that()
+
.areAssignableTo("org.apache.iotdb.confignode.conf.ConfigNodeDescriptor")
+ .should()
+ .callMethod(Properties.class, "getProperty", String.class)
+ .orShould()
+ .callMethod(Properties.class, "getProperty", String.class,
String.class);
+
+ rule.check(allClasses);
+ }
+}
diff --git a/iotdb-core/datanode/pom.xml b/iotdb-core/datanode/pom.xml
index 510db46ad4c..6194b6272a4 100644
--- a/iotdb-core/datanode/pom.xml
+++ b/iotdb-core/datanode/pom.xml
@@ -368,6 +368,12 @@
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.tngtech.archunit</groupId>
+ <artifactId>archunit</artifactId>
+ <version>1.3.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
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 e7b7139ce51..7d6426f0bc7 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
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.ConfigurationFileUtils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.conf.TrimProperties;
import org.apache.iotdb.commons.exception.BadNodeUrlException;
import org.apache.iotdb.commons.schema.SchemaConstant;
import org.apache.iotdb.commons.service.metric.MetricService;
@@ -131,8 +132,10 @@ public class IoTDBDescriptor {
for (IPropertiesLoader loader : propertiesLoaderServiceLoader) {
LOGGER.info("Will reload properties from {} ",
loader.getClass().getName());
Properties properties = loader.loadProperties();
+ TrimProperties trimProperties = new TrimProperties();
+ trimProperties.putAll(properties);
try {
- loadProperties(properties);
+ loadProperties(trimProperties);
} catch (Exception e) {
LOGGER.error(
"Failed to reload properties from {}, reject DataNode startup.",
@@ -199,13 +202,13 @@ public class IoTDBDescriptor {
/** load a property file and set TsfileDBConfig variables. */
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
private void loadProps() {
- Properties commonProperties = new Properties();
+ TrimProperties commonProperties = new TrimProperties();
// if new properties file exist, skip old properties files
URL url = getPropsUrl(CommonConfig.SYSTEM_CONFIG_NAME);
if (url != null) {
try (InputStream inputStream = url.openStream()) {
LOGGER.info("Start to read config file {}", url);
- Properties properties = new Properties();
+ Properties properties = new TrimProperties();
properties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
commonProperties.putAll(properties);
loadProperties(commonProperties);
@@ -234,7 +237,7 @@ public class IoTDBDescriptor {
}
}
- public void loadProperties(Properties properties) throws
BadNodeUrlException, IOException {
+ public void loadProperties(TrimProperties properties) throws
BadNodeUrlException, IOException {
conf.setClusterName(
properties.getProperty(IoTDBConstant.CLUSTER_NAME,
conf.getClusterName()).trim());
@@ -1095,13 +1098,13 @@ public class IoTDBDescriptor {
loadPipeConsensusProps(properties);
}
- private void reloadConsensusProps(Properties properties) throws IOException {
+ private void reloadConsensusProps(TrimProperties properties) throws
IOException {
loadIoTConsensusProps(properties);
loadPipeConsensusProps(properties);
DataRegionConsensusImpl.reloadConsensusConfig();
}
- private void loadIoTConsensusProps(Properties properties) throws IOException
{
+ private void loadIoTConsensusProps(TrimProperties properties) throws
IOException {
conf.setMaxLogEntriesNumPerBatch(
Integer.parseInt(
properties
@@ -1144,7 +1147,7 @@ public class IoTDBDescriptor {
.trim()));
}
- private void loadPipeConsensusProps(Properties properties) throws
IOException {
+ private void loadPipeConsensusProps(TrimProperties properties) throws
IOException {
conf.setPipeConsensusPipelineSize(
Integer.parseInt(
properties.getProperty(
@@ -1156,7 +1159,7 @@ public class IoTDBDescriptor {
}
}
- private void loadAuthorCache(Properties properties) {
+ private void loadAuthorCache(TrimProperties properties) {
conf.setAuthorCacheSize(
Integer.parseInt(
properties.getProperty(
@@ -1167,7 +1170,7 @@ public class IoTDBDescriptor {
"author_cache_expire_time",
String.valueOf(conf.getAuthorCacheExpireTime()))));
}
- private void loadWALProps(Properties properties) throws IOException {
+ private void loadWALProps(TrimProperties properties) throws IOException {
conf.setWalMode(
WALMode.valueOf((properties.getProperty("wal_mode",
conf.getWalMode().toString()))));
@@ -1199,7 +1202,7 @@ public class IoTDBDescriptor {
loadWALHotModifiedProps(properties);
}
- private void loadCompactionHotModifiedProps(Properties properties)
+ private void loadCompactionHotModifiedProps(TrimProperties properties)
throws InterruptedException, IOException {
boolean compactionTaskConfigHotModified =
loadCompactionTaskHotModifiedProps(properties);
if (compactionTaskConfigHotModified) {
@@ -1240,7 +1243,7 @@ public class IoTDBDescriptor {
Boolean.toString(conf.isEnableAutoRepairCompaction()))));
}
- private boolean loadCompactionTaskHotModifiedProps(Properties properties)
throws IOException {
+ private boolean loadCompactionTaskHotModifiedProps(TrimProperties
properties) throws IOException {
boolean configModified = false;
// update merge_write_throughput_mb_per_sec
int compactionWriteThroughput =
conf.getCompactionWriteThroughputMbPerSec();
@@ -1426,7 +1429,7 @@ public class IoTDBDescriptor {
return configModified;
}
- private boolean loadCompactionThreadCountHotModifiedProps(Properties
properties)
+ private boolean loadCompactionThreadCountHotModifiedProps(TrimProperties
properties)
throws IOException {
int newConfigCompactionThreadCount =
Integer.parseInt(
@@ -1447,7 +1450,7 @@ public class IoTDBDescriptor {
return true;
}
- private boolean loadCompactionSubTaskCountHotModifiedProps(Properties
properties)
+ private boolean loadCompactionSubTaskCountHotModifiedProps(TrimProperties
properties)
throws IOException {
int newConfigSubtaskNum =
Integer.parseInt(
@@ -1465,7 +1468,7 @@ public class IoTDBDescriptor {
return true;
}
- private boolean loadCompactionIsEnabledHotModifiedProps(Properties
properties)
+ private boolean loadCompactionIsEnabledHotModifiedProps(TrimProperties
properties)
throws IOException {
boolean isCompactionEnabled =
conf.isEnableSeqSpaceCompaction()
@@ -1500,7 +1503,7 @@ public class IoTDBDescriptor {
return !isCompactionEnabled && compactionEnabledInNewConfig;
}
- private void loadWALHotModifiedProps(Properties properties) throws
IOException {
+ private void loadWALHotModifiedProps(TrimProperties properties) throws
IOException {
long walAsyncModeFsyncDelayInMs =
Long.parseLong(
properties.getProperty(
@@ -1587,7 +1590,7 @@ public class IoTDBDescriptor {
}
}
- private String getWalThrottleThreshold(Properties prop) throws IOException {
+ private String getWalThrottleThreshold(TrimProperties prop) throws
IOException {
String old_throttleThreshold =
prop.getProperty(DEFAULT_WAL_THRESHOLD_NAME[0], null);
if (old_throttleThreshold != null) {
LOGGER.warn(
@@ -1628,7 +1631,7 @@ public class IoTDBDescriptor {
return Math.max(Math.min(newThrottleThreshold, MAX_THROTTLE_THRESHOLD),
MIN_THROTTLE_THRESHOLD);
}
- private void loadAutoCreateSchemaProps(Properties properties, boolean
startUp)
+ private void loadAutoCreateSchemaProps(TrimProperties properties, boolean
startUp)
throws IOException {
conf.setAutoCreateSchemaEnabled(
Boolean.parseBoolean(
@@ -1689,7 +1692,7 @@ public class IoTDBDescriptor {
ConfigurationFileUtils.getConfigurationDefaultValue("default_text_encoding")));
}
- private void loadTsFileProps(Properties properties) throws IOException {
+ private void loadTsFileProps(TrimProperties properties) throws IOException {
TSFileDescriptor.getInstance()
.getConfig()
.setGroupSizeInByte(
@@ -1766,8 +1769,11 @@ public class IoTDBDescriptor {
}
// Mqtt related
- private void loadMqttProps(Properties properties) {
- conf.setMqttDir(properties.getProperty("mqtt_root_dir",
conf.getMqttDir()));
+ private void loadMqttProps(TrimProperties properties) {
+ conf.setMqttDir(
+ Optional.ofNullable(properties.getProperty("mqtt_root_dir",
conf.getMqttDir()))
+ .map(String::trim)
+ .orElse(conf.getMqttDir()));
if (properties.getProperty(IoTDBConstant.MQTT_HOST_NAME) != null) {
conf.setMqttHost(properties.getProperty(IoTDBConstant.MQTT_HOST_NAME));
@@ -1803,7 +1809,7 @@ public class IoTDBDescriptor {
}
// timed flush memtable
- private void loadTimedService(Properties properties) throws IOException {
+ private void loadTimedService(TrimProperties properties) throws IOException {
conf.setEnableTimedFlushSeqMemtable(
Boolean.parseBoolean(
properties.getProperty(
@@ -1876,7 +1882,7 @@ public class IoTDBDescriptor {
return tierDataDirs;
}
- public synchronized void loadHotModifiedProps(Properties properties)
+ public synchronized void loadHotModifiedProps(TrimProperties properties)
throws QueryProcessException {
try {
// update data dirs
@@ -2070,7 +2076,7 @@ public class IoTDBDescriptor {
return;
}
- Properties commonProperties = new Properties();
+ TrimProperties commonProperties = new TrimProperties();
try (InputStream inputStream = url.openStream()) {
LOGGER.info("Start to reload config file {}", url);
commonProperties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
@@ -2086,7 +2092,7 @@ public class IoTDBDescriptor {
reloadMetricProperties(commonProperties);
}
- public void reloadMetricProperties(Properties properties) {
+ public void reloadMetricProperties(TrimProperties properties) {
ReloadLevel reloadLevel =
MetricConfigDescriptor.getInstance().loadHotProps(properties, false);
LOGGER.info("Reload metric service in level {}", reloadLevel);
if (reloadLevel == ReloadLevel.RESTART_INTERNAL_REPORTER) {
@@ -2103,7 +2109,7 @@ public class IoTDBDescriptor {
}
}
- private void initMemoryAllocate(Properties properties) {
+ private void initMemoryAllocate(TrimProperties properties) {
String memoryAllocateProportion =
properties.getProperty("datanode_memory_proportion", null);
if (memoryAllocateProportion == null) {
memoryAllocateProportion =
@@ -2215,7 +2221,7 @@ public class IoTDBDescriptor {
}
@SuppressWarnings("java:S3518")
- private void initStorageEngineAllocate(Properties properties) {
+ private void initStorageEngineAllocate(TrimProperties properties) {
long storageMemoryTotal = conf.getAllocateMemoryForStorageEngine();
String valueOfStorageEngineMemoryProportion =
properties.getProperty("storage_engine_memory_proportion");
@@ -2270,7 +2276,7 @@ public class IoTDBDescriptor {
}
@SuppressWarnings("squid:S3518")
- private void initSchemaMemoryAllocate(Properties properties) {
+ private void initSchemaMemoryAllocate(TrimProperties properties) {
long schemaMemoryTotal = conf.getAllocateMemoryForSchema();
String schemaMemoryPortionInput =
properties.getProperty("schema_memory_proportion");
@@ -2328,7 +2334,7 @@ public class IoTDBDescriptor {
LOGGER.info("allocateMemoryForPartitionCache = {}",
conf.getAllocateMemoryForPartitionCache());
}
- private void loadLoadTsFileProps(Properties properties) {
+ private void loadLoadTsFileProps(TrimProperties properties) {
conf.setMaxAllocateMemoryRatioForLoad(
Double.parseDouble(
properties.getProperty(
@@ -2406,7 +2412,7 @@ public class IoTDBDescriptor {
}
}
- private void loadLoadTsFileHotModifiedProp(Properties properties) throws
IOException {
+ private void loadLoadTsFileHotModifiedProp(TrimProperties properties) throws
IOException {
conf.setLoadCleanupTaskExecutionDelayTimeSeconds(
Long.parseLong(
properties.getProperty(
@@ -2447,7 +2453,7 @@ public class IoTDBDescriptor {
}
@SuppressWarnings("squid:S3518") // "proportionSum" can't be zero
- private void loadUDFProps(Properties properties) {
+ private void loadUDFProps(TrimProperties properties) {
String initialByteArrayLengthForMemoryControl =
properties.getProperty("udf_initial_byte_array_length_for_memory_control");
if (initialByteArrayLengthForMemoryControl != null) {
@@ -2490,7 +2496,7 @@ public class IoTDBDescriptor {
}
}
- private void initThriftSSL(Properties properties) {
+ private void initThriftSSL(TrimProperties properties) {
conf.setEnableSSL(
Boolean.parseBoolean(
properties.getProperty("enable_thrift_ssl",
Boolean.toString(conf.isEnableSSL()))));
@@ -2498,8 +2504,8 @@ public class IoTDBDescriptor {
conf.setKeyStorePwd(properties.getProperty("key_store_pwd",
conf.getKeyStorePath()).trim());
}
- private void loadTriggerProps(Properties properties) {
- conf.setTriggerDir(properties.getProperty("trigger_lib_dir",
conf.getTriggerDir()));
+ private void loadTriggerProps(TrimProperties properties) {
+ conf.setTriggerDir(properties.getProperty("trigger_lib_dir",
conf.getTriggerDir()).trim());
conf.setRetryNumToFindStatefulTrigger(
Integer.parseInt(
properties.getProperty(
@@ -2545,8 +2551,11 @@ public class IoTDBDescriptor {
Integer.toString(conf.getTriggerForwardMQTTPoolSize()))));
}
- private void loadPipeProps(Properties properties) {
- conf.setPipeLibDir(properties.getProperty("pipe_lib_dir",
conf.getPipeLibDir()));
+ private void loadPipeProps(TrimProperties properties) {
+ conf.setPipeLibDir(
+ Optional.ofNullable(properties.getProperty("pipe_lib_dir",
conf.getPipeLibDir()))
+ .map(String::trim)
+ .orElse(conf.getPipeLibDir()));
conf.setPipeReceiverFileDirs(
Arrays.stream(
@@ -2572,7 +2581,7 @@ public class IoTDBDescriptor {
.toArray(String[]::new));
}
- private void loadCQProps(Properties properties) {
+ private void loadCQProps(TrimProperties properties) {
conf.setContinuousQueryThreadNum(
Integer.parseInt(
properties.getProperty(
@@ -2589,7 +2598,7 @@ public class IoTDBDescriptor {
false));
}
- public void loadClusterProps(Properties properties) throws IOException {
+ public void loadClusterProps(TrimProperties properties) throws IOException {
String configNodeUrls =
properties.getProperty(IoTDBConstant.DN_SEED_CONFIG_NODE);
if (configNodeUrls == null) {
configNodeUrls =
properties.getProperty(IoTDBConstant.DN_TARGET_CONFIG_NODE_LIST);
@@ -2644,7 +2653,7 @@ public class IoTDBDescriptor {
.trim()));
}
- public void loadShuffleProps(Properties properties) {
+ public void loadShuffleProps(TrimProperties properties) {
conf.setMppDataExchangePort(
Integer.parseInt(
properties.getProperty(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
index 48725ef1839..2e9f49917f0 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.conf.rest;
import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.conf.TrimProperties;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.slf4j.Logger;
@@ -33,7 +34,6 @@ import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.Properties;
public class IoTDBRestServiceDescriptor {
private static final Logger logger =
LoggerFactory.getLogger(IoTDBRestServiceDescriptor.class);
@@ -43,9 +43,9 @@ public class IoTDBRestServiceDescriptor {
protected IoTDBRestServiceDescriptor() {
URL systemConfig = getPropsUrl(CommonConfig.SYSTEM_CONFIG_NAME);
if (systemConfig != null) {
- Properties properties = loadProps(CommonConfig.SYSTEM_CONFIG_NAME);
- if (properties != null) {
- loadProps(properties);
+ TrimProperties trimProperties =
loadProps(CommonConfig.SYSTEM_CONFIG_NAME);
+ if (trimProperties != null) {
+ loadProps(trimProperties);
}
}
}
@@ -56,7 +56,7 @@ public class IoTDBRestServiceDescriptor {
/** load an property file. */
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
- private Properties loadProps(String configName) {
+ private TrimProperties loadProps(String configName) {
URL url = getPropsUrl(configName);
if (url == null) {
logger.warn("Couldn't load the REST Service configuration from any of
the known sources.");
@@ -64,9 +64,9 @@ public class IoTDBRestServiceDescriptor {
}
try (InputStream inputStream = url.openStream()) {
logger.info("Start to read config file {}", url);
- Properties properties = new Properties();
- properties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
- return properties;
+ TrimProperties trimProperties = new TrimProperties();
+ trimProperties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
+ return trimProperties;
} catch (FileNotFoundException e) {
logger.warn("REST service fail to find config file {}", url, e);
} catch (IOException e) {
@@ -77,7 +77,7 @@ public class IoTDBRestServiceDescriptor {
return null;
}
- private void loadProps(Properties properties) {
+ private void loadProps(TrimProperties properties) {
conf.setEnableRestService(
Boolean.parseBoolean(
properties.getProperty(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
index 56470075c77..68f76c942f0 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
@@ -30,6 +30,7 @@ import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.ConfigurationFileUtils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.conf.TrimProperties;
import org.apache.iotdb.commons.consensus.DataRegionId;
import org.apache.iotdb.commons.consensus.index.ProgressIndex;
import org.apache.iotdb.commons.exception.IllegalPathException;
@@ -91,7 +92,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
@@ -656,8 +656,8 @@ public class StorageEngine implements IService {
if (newConfigItems.isEmpty()) {
return tsStatus;
}
- Properties properties = new Properties();
- properties.putAll(newConfigItems);
+ TrimProperties newConfigProperties = new TrimProperties();
+ newConfigProperties.putAll(newConfigItems);
URL configFileUrl =
IoTDBDescriptor.getPropsUrl(CommonConfig.SYSTEM_CONFIG_NAME);
if (configFileUrl == null || !(new
File(configFileUrl.getFile()).exists())) {
@@ -667,30 +667,31 @@ public class StorageEngine implements IService {
tsStatus = RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR, msg);
LOGGER.warn(msg);
try {
- IoTDBDescriptor.getInstance().loadHotModifiedProps(properties);
- IoTDBDescriptor.getInstance().reloadMetricProperties(properties);
+
IoTDBDescriptor.getInstance().loadHotModifiedProps(newConfigProperties);
+
IoTDBDescriptor.getInstance().reloadMetricProperties(newConfigProperties);
} catch (Exception e) {
return RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR,
e.getMessage());
}
return tsStatus;
}
- // 1. append new configuration properties to configuration file
try {
- ConfigurationFileUtils.updateConfigurationFile(new
File(configFileUrl.getFile()), properties);
+ ConfigurationFileUtils.updateConfiguration(
+ new File(configFileUrl.getFile()),
+ newConfigProperties,
+ mergedProperties -> {
+ try {
+
IoTDBDescriptor.getInstance().loadHotModifiedProps(mergedProperties);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ });
} catch (Exception e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
return RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR,
e.getMessage());
}
-
- // 2. load hot modified properties
- try {
- IoTDBDescriptor.getInstance().loadHotModifiedProps();
- } catch (Exception e) {
- return RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR,
e.getMessage());
- }
return tsStatus;
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/conf/PropertiesTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/conf/PropertiesTest.java
new file mode 100755
index 00000000000..d547963d322
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/conf/PropertiesTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.db.conf;
+
+import org.apache.iotdb.commons.conf.TrimProperties;
+
+import com.tngtech.archunit.core.domain.JavaClasses;
+import com.tngtech.archunit.core.importer.ClassFileImporter;
+import com.tngtech.archunit.core.importer.ImportOption;
+import com.tngtech.archunit.lang.ArchRule;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.file.metadata.enums.TSEncoding;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Properties;
+
+import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
+
+public class PropertiesTest {
+ @Test
+ public void PropertiesWithSpace() {
+ IoTDBDescriptor descriptor = IoTDBDescriptor.getInstance();
+ TrimProperties properties = new TrimProperties();
+ properties.setProperty("load_active_listening_max_thread_num", "8 "); //
data type: int
+ properties.setProperty("load_active_listening_enable", "true "); // data
type: Boolean
+ properties.setProperty("into_operation_buffer_size_in_byte", "104857600
"); // data type: long
+ properties.setProperty("wal_min_effective_info_ratio", "0.1 "); // data
type: Double
+ properties.setProperty("floating_string_infer_type", "DOUBLE "); // data
type: TSDataType
+ properties.setProperty("default_boolean_encoding", "RLE "); // data type:
TSEncoding
+ properties.setProperty("expired_data_ratio", "0.3 "); // data type: float
+
+ try {
+ descriptor.loadProperties(properties);
+ Assert.assertEquals(8,
descriptor.getConfig().getLoadActiveListeningMaxThreadNum());
+ Assert.assertTrue(descriptor.getConfig().getLoadActiveListeningEnable());
+ Assert.assertEquals(104857600,
descriptor.getConfig().getIntoOperationBufferSizeInByte());
+ Assert.assertEquals(0.1,
descriptor.getConfig().getWalMinEffectiveInfoRatio(), 0.000001);
+ Assert.assertEquals(TSDataType.DOUBLE,
descriptor.getConfig().getFloatingStringInferType());
+ Assert.assertEquals(TSEncoding.RLE,
descriptor.getConfig().getDefaultBooleanEncoding());
+ Assert.assertEquals(0.3, descriptor.getConfig().getExpiredDataRatio(),
0.000001);
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+
+ properties.setProperty("load_active_listening_max_thread_num", " 8 ");
+ properties.setProperty("load_active_listening_enable", " true ");
+ properties.setProperty("into_operation_buffer_size_in_byte", " 104857600
");
+ properties.setProperty("wal_min_effective_info_ratio", " 0.1 ");
+ properties.setProperty("floating_string_infer_type", " DOUBLE ");
+ properties.setProperty("default_boolean_encoding", " RLE ");
+ properties.setProperty("expired_data_ratio", " 0.3 ");
+
+ try {
+ descriptor.loadHotModifiedProps(properties);
+ Assert.assertEquals(8,
descriptor.getConfig().getLoadActiveListeningMaxThreadNum());
+ Assert.assertTrue(descriptor.getConfig().getLoadActiveListeningEnable());
+ Assert.assertEquals(104857600,
descriptor.getConfig().getIntoOperationBufferSizeInByte());
+ Assert.assertEquals(0.1,
descriptor.getConfig().getWalMinEffectiveInfoRatio(), 0.000001);
+ Assert.assertEquals(TSDataType.DOUBLE,
descriptor.getConfig().getFloatingStringInferType());
+ Assert.assertEquals(TSEncoding.RLE,
descriptor.getConfig().getDefaultBooleanEncoding());
+ Assert.assertEquals(0.3, descriptor.getConfig().getExpiredDataRatio(),
0.000001);
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void TrimPropertiesOnly() {
+ JavaClasses allClasses =
+ new ClassFileImporter()
+ .withImportOption(new ImportOption.DoNotIncludeTests())
+ .importPackages("org.apache.iotdb");
+
+ ArchRule rule =
+ noClasses()
+ .that()
+ .areAssignableTo("org.apache.iotdb.db.conf.IoTDBDescriptor")
+ .or()
+
.areAssignableTo("org.apache.iotdb.db.conf.rest.IoTDBRestServiceDescriptor")
+ .or()
+ .areAssignableTo("org.apache.iotdb.commons.conf.CommonDescriptor")
+ .should()
+ .callMethod(Properties.class, "getProperty", String.class)
+ .orShould()
+ .callMethod(Properties.class, "getProperty", String.class,
String.class);
+
+ rule.check(allClasses);
+ }
+}
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
index f1ec288d47a..11decb83369 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.metrics.utils.InternalReporterType;
import org.apache.iotdb.metrics.utils.MetricLevel;
import org.apache.iotdb.metrics.utils.ReporterType;
+import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
@@ -174,7 +175,10 @@ public class MetricConfigDescriptor {
/** Get property from confignode or datanode. */
private String getProperty(
String target, String defaultValue, Properties properties, boolean
isConfigNode) {
- return properties.getProperty((isConfigNode ? "cn_" : "dn_") + target,
defaultValue);
+ return Optional.ofNullable(
+ properties.getProperty((isConfigNode ? "cn_" : "dn_") + target,
defaultValue))
+ .map(String::trim)
+ .orElse(defaultValue);
}
private static class MetricConfigDescriptorHolder {
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
index 361f3031d4f..1026ed6aa0a 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
@@ -27,7 +27,6 @@ import org.apache.iotdb.confignode.rpc.thrift.TGlobalConfig;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
-import java.util.Properties;
public class CommonDescriptor {
@@ -71,7 +70,7 @@ public class CommonDescriptor {
config.setProcedureWalFolder(systemDir + File.separator + "procedure");
}
- public void loadCommonProps(Properties properties) throws IOException {
+ public void loadCommonProps(TrimProperties properties) throws IOException {
config.setAuthorizerProvider(
properties.getProperty("authorizer_provider_class",
config.getAuthorizerProvider()).trim());
// if using org.apache.iotdb.db.auth.authorizer.OpenIdAuthorizer,
openID_url is needed.
@@ -248,7 +247,7 @@ public class CommonDescriptor {
loadBinaryAllocatorProps(properties);
}
- private void loadPipeProps(Properties properties) {
+ private void loadPipeProps(TrimProperties properties) {
config.setPipeNonForwardingEventsProgressReportInterval(
Integer.parseInt(
properties.getProperty(
@@ -639,7 +638,7 @@ public class CommonDescriptor {
String.valueOf(config.getPipeEventReferenceEliminateIntervalSeconds()))));
}
- private void loadSubscriptionProps(Properties properties) {
+ private void loadSubscriptionProps(TrimProperties properties) {
config.setSubscriptionCacheMemoryUsagePercentage(
Float.parseFloat(
properties.getProperty(
@@ -727,7 +726,7 @@ public class CommonDescriptor {
String.valueOf(config.getSubscriptionMetaSyncerSyncIntervalMinutes()))));
}
- public void loadRetryProperties(Properties properties) throws IOException {
+ public void loadRetryProperties(TrimProperties properties) throws
IOException {
config.setRemoteWriteMaxRetryDurationInMs(
Long.parseLong(
properties.getProperty(
@@ -743,7 +742,7 @@ public class CommonDescriptor {
"enable_retry_for_unknown_error"))));
}
- public void loadBinaryAllocatorProps(Properties properties) {
+ public void loadBinaryAllocatorProps(TrimProperties properties) {
config.setEnableBinaryAllocator(
Boolean.parseBoolean(
properties.getProperty(
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 0857b493b9a..f5702143dd9 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
@@ -31,6 +31,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
+import java.io.StringReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -247,19 +248,32 @@ public class ConfigurationFileUtils {
return ignoredConfigItems;
}
- public static void updateConfigurationFile(File file, Properties
newConfigItems)
+ public static void updateConfiguration(
+ File file, Properties newConfigItems, LoadHotModifiedPropsFunc
loadHotModifiedPropertiesFunc)
throws IOException, InterruptedException {
File lockFile = new File(file.getPath() + lockFileSuffix);
acquireTargetFileLock(lockFile);
try {
// read configuration file
List<String> lines = new ArrayList<>();
+ TrimProperties mergedProps = new TrimProperties();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
+ mergedProps.load(new StringReader(line));
}
}
+ // overwrite old configuration with new value
+ for (String key : newConfigItems.stringPropertyNames()) {
+ mergedProps.put(key, newConfigItems.getProperty(key));
+ }
+
+ // load hot modified properties
+ if (loadHotModifiedPropertiesFunc != null) {
+ loadHotModifiedPropertiesFunc.loadHotModifiedProperties(mergedProps);
+ }
+
// generate new configuration file content in memory
StringBuilder contentsOfNewConfigurationFile = new StringBuilder();
for (String currentLine : lines) {
@@ -341,4 +355,10 @@ public class ConfigurationFileUtils {
private static void releaseFileLock(File file) throws IOException {
Files.deleteIfExists(file.toPath());
}
+
+ @FunctionalInterface
+ public interface LoadHotModifiedPropsFunc {
+ void loadHotModifiedProperties(TrimProperties properties)
+ throws IOException, InterruptedException;
+ }
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/TrimProperties.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/TrimProperties.java
new file mode 100644
index 00000000000..aa627367e82
--- /dev/null
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/TrimProperties.java
@@ -0,0 +1,50 @@
+/*
+ * 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.commons.conf;
+
+import java.util.Optional;
+import java.util.Properties;
+
+public class TrimProperties extends Properties {
+ @Override
+ public synchronized Object get(Object key) {
+ Object value = super.get(key);
+ if (value instanceof String) {
+ return ((String) value).trim();
+ }
+ return value;
+ }
+
+ @Override
+ public synchronized Object put(Object key, Object value) {
+ if (value instanceof String) {
+ value = ((String) value).trim();
+ }
+ return super.put(key, value);
+ }
+
+ @Override
+ public synchronized String getProperty(String key, String defaultValue) {
+ String val = getProperty(key);
+ if (defaultValue != null) {
+ defaultValue = defaultValue.trim();
+ }
+ return Optional.ofNullable(val).map(String::trim).orElse(defaultValue);
+ }
+}