This is an automated email from the ASF dual-hosted git repository. CRZbulabula pushed a commit to branch fix_v2_995_topology_probing_hot_reload in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 08a89f8882e7adbd1b91184c639755c0d7d3495b Author: Yongzao <[email protected]> AuthorDate: Fri Jun 12 18:26:33 2026 +0800 Fix enable_topology_probing hot-reload by uncommenting it in the config template enable_topology_probing declares effectiveMode: hot_reload and the ConfigNode implements the hot-reload start/stop logic, but 'set configuration "enable_topology_probing"="true"' was rejected with 301 "immutable or undefined". Root cause: the item was left commented out (# enable_topology_probing=false) in iotdb-system.properties.template. ConfigurationFileUtils.getConfigurationItemsFromTemplate only parses uncommented key=value lines into the default-value map, so filterInvalidConfigItems treated the key as undefined and dropped it before it could reach the hot-reload path. Uncommenting it makes it a bare default like every other working hot_reload item (e.g. slow_query_threshold). Add regression tests: - ConfigurationFileUtilsTest.checkHotReloadItemsAreUncommentedInTemplate scans the template and fails if any hot_reload item is left commented out (while tolerating keys that also have an uncommented variant, e.g. the Windows/Unix path pairs). - IoTDBSetConfigurationIT.testSetHotReloadTopologyProbing verifies 'set configuration' accepts the item and persists it to the ConfigNode config file. --- .../iotdb/db/it/IoTDBSetConfigurationIT.java | 21 +++++++ .../iotdb/db/utils/ConfigurationFileUtilsTest.java | 71 ++++++++++++++++++++++ .../conf/iotdb-system.properties.template | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) 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 96ee0bc30c1..b430ddc754b 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 @@ -88,6 +88,27 @@ public class IoTDBSetConfigurationIT { "enable_cross_space_compaction=false"))); } + /** + * Regression test for V2-995: {@code enable_topology_probing} is declared {@code effectiveMode: + * hot_reload}, so {@code set configuration} must accept it (instead of rejecting it as "immutable + * or undefined") and persist it to the config file. This used to fail because the item was left + * commented out in the template, hiding it from the default-value map. + */ + @Test + public void testSetHotReloadTopologyProbing() { + try (Connection connection = EnvFactory.getEnv().getConnection(); + Statement statement = connection.createStatement()) { + statement.execute("set configuration \"enable_topology_probing\"=\"true\""); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + Assert.assertTrue( + EnvFactory.getEnv().getConfigNodeWrapperList().stream() + .allMatch( + nodeWrapper -> + checkConfigFileContains(nodeWrapper, "enable_topology_probing=true"))); + } + @Test public void testSetClusterName() throws Exception { // set cluster name on cn and dn diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java index af0fc1ae83e..cf06df887f2 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.utils; +import org.apache.iotdb.commons.conf.CommonConfig; import org.apache.iotdb.commons.conf.ConfigurationFileUtils; import org.apache.iotdb.db.utils.constant.TestConstant; @@ -26,13 +27,18 @@ import org.junit.After; import org.junit.Assert; import org.junit.Test; +import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.file.Files; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Properties; +import java.util.Set; public class ConfigurationFileUtilsTest { @@ -89,6 +95,71 @@ public class ConfigurationFileUtilsTest { } } + /** + * Regression guard for V2-995: a configuration item declared {@code effectiveMode: hot_reload} + * must have its {@code key=value} line left uncommented in the template. {@code + * getConfigurationItemsFromTemplate} only parses uncommented lines, so a commented hot_reload + * item never enters {@code configuration2DefaultValue}; {@code filterInvalidConfigItems} then + * treats it as undefined and {@code set configuration} rejects it with "immutable or undefined", + * silently disabling the advertised hot-reload entry point. + */ + @Test + public void checkHotReloadItemsAreUncommentedInTemplate() throws IOException { + // Keys whose value line appears uncommented at least once. Some keys (e.g. dn_data_dirs) list a + // commented Windows-path variant next to an uncommented Unix-path variant; only the uncommented + // one is parsed, so such keys are fine and must not be flagged. + Set<String> uncommentedKeys = new HashSet<>(); + // Keys with a commented value line whose enclosing block declares effectiveMode: hot_reload. + Set<String> commentedHotReloadKeys = new HashSet<>(); + try (InputStream inputStream = + ConfigurationFileUtilsTest.class + .getClassLoader() + .getResourceAsStream(CommonConfig.SYSTEM_CONFIG_TEMPLATE_NAME); + BufferedReader reader = + new BufferedReader(new InputStreamReader(Objects.requireNonNull(inputStream)))) { + String line; + ConfigurationFileUtils.EffectiveModeType currentMode = null; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.isEmpty()) { + // Blank line separates configuration blocks; reset the accumulated effectiveMode. + currentMode = null; + continue; + } + if (line.startsWith("# effectiveMode:")) { + currentMode = + ConfigurationFileUtils.EffectiveModeType.getEffectiveMode( + line.substring("# effectiveMode:".length()).trim()); + continue; + } + // Detect the (possibly commented) "key=value" line that closes a block. + String stripped = line.startsWith("#") ? line.substring(1).trim() : line; + int equalsIndex = stripped.indexOf('='); + boolean isValueLine = + equalsIndex > 0 && stripped.substring(0, equalsIndex).trim().matches("[a-zA-Z0-9_.]+"); + if (!isValueLine) { + continue; + } + String key = stripped.substring(0, equalsIndex).trim(); + if (line.startsWith("#")) { + if (currentMode == ConfigurationFileUtils.EffectiveModeType.HOT_RELOAD) { + commentedHotReloadKeys.add(key); + } + } else { + uncommentedKeys.add(key); + } + // A value line ends the current block's effectiveMode scope. + currentMode = null; + } + } + commentedHotReloadKeys.removeAll(uncommentedKeys); + Assert.assertTrue( + "hot_reload configuration items must be uncommented in the template so that " + + "'set configuration' can hot-reload them; commented hot_reload items found: " + + commentedHotReloadKeys, + commentedHotReloadKeys.isEmpty()); + } + private void generateFile(File file, String content) throws IOException { Files.write(file.toPath(), content.getBytes()); } diff --git a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template index 8e4808cec2f..3445d82bfe9 100644 --- a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template +++ b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template @@ -747,7 +747,7 @@ failure_detector_phi_acceptable_pause_in_ms=10000 # Whether to enable topology probing between DataNodes # effectiveMode: hot_reload # Datatype: Boolean -# enable_topology_probing=false +enable_topology_probing=false # Base interval in ms for topology probing between DataNodes # effectiveMode: restart
