This is an automated email from the ASF dual-hosted git repository.
JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 0b48a35c2c2 Fix show configuration displaying raw value instead of
effective value (#18108)
0b48a35c2c2 is described below
commit 0b48a35c2c28b19f86271cb2b759aaaabc58c71f
Author: Jackie Tien <[email protected]>
AuthorDate: Mon Jul 6 15:54:43 2026 +0800
Fix show configuration displaying raw value instead of effective value
(#18108)
---
.../it/db/it/IoTDBLoadConfigurationTableIT.java | 94 ++++++++++++++++++++++
.../org/apache/iotdb/db/conf/IoTDBDescriptor.java | 33 ++++++++
2 files changed, 127 insertions(+)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
index 53e8bc9487e..398a7f0e1e4 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
@@ -19,6 +19,8 @@
package org.apache.iotdb.relational.it.db.it;
+import org.apache.iotdb.isession.ITableSession;
+import org.apache.iotdb.isession.SessionDataSet;
import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -40,6 +42,8 @@ import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
import java.sql.Connection;
import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
@RunWith(IoTDBTestRunner.class)
@Category({TableLocalStandaloneIT.class, TableClusterIT.class})
@@ -82,4 +86,94 @@ public class IoTDBLoadConfigurationTableIT {
}
}
}
+
+ // `show configuration` must display the in-memory effective value, not the
raw config-file
+ // value. Several hot-reloaded parameters have setters that rewrite the
loaded value (e.g.
+ // `if (x > 0) setX(x)` skips non-positive values;
loadFixedSizeLimitForQuery rewrites `<=0`
+ // to a computed default). This test verifies those keys show the effective
value after
+ // `load configuration`.
+ @Test
+ public void showConfigurationDisplaysEffectiveValue() throws Exception {
+ DataNodeWrapper dataNodeWrapper =
EnvFactory.getEnv().getDataNodeWrapper(0);
+ String confPath =
+ dataNodeWrapper.getNodePath()
+ + File.separator
+ + "conf"
+ + File.separator
+ + "iotdb-system.properties";
+
+ // Case 1: non-positive guard params (`if (x > 0) setX(x)`) must display
the effective
+ // default value, not the raw file value (0 / -1).
+ Map<String, String> afterGuardReload =
+ appendLinesLoadAndShow(
+ confPath,
+ "cte_buffer_size_in_bytes=0",
+ "max_rows_in_cte_buffer=-1",
+ "max_sub_task_num_for_information_table_scan=0");
+ Assert.assertEquals("131072",
afterGuardReload.get("cte_buffer_size_in_bytes"));
+ Assert.assertEquals("1000",
afterGuardReload.get("max_rows_in_cte_buffer"));
+ Assert.assertEquals("4",
afterGuardReload.get("max_sub_task_num_for_information_table_scan"));
+
+ // Case 2: a valid value is not rewritten, so display must equal the file
value (regression).
+ Map<String, String> afterValidReload =
+ appendLinesLoadAndShow(confPath, "cte_buffer_size_in_bytes=262144");
+ Assert.assertEquals("262144",
afterValidReload.get("cte_buffer_size_in_bytes"));
+
+ // Case 3: params whose template default is 0 are always rewritten to a
computed default,
+ // so they must never display 0 (this was always wrong, even without a bad
file value).
+ Map<String, String> defaultsReload = appendLinesLoadAndShow(confPath);
+ assertPositiveNonZero(defaultsReload, "sort_buffer_size_in_bytes");
+ assertPositiveNonZero(defaultsReload,
"mods_cache_size_limit_per_fi_in_bytes");
+ }
+
+ // Appends the given lines to the config file, runs `load configuration`,
fetches the
+ // `show configuration` result, and restores the file to its original length.
+ private Map<String, String> appendLinesLoadAndShow(String confPath,
String... lines)
+ throws Exception {
+ long length = new File(confPath).length();
+ try {
+ if (lines.length > 0) {
+ try (FileWriter fileWriter = new FileWriter(confPath, true)) {
+ fileWriter.write(System.lineSeparator());
+ for (String line : lines) {
+ fileWriter.write(line);
+ fileWriter.write(System.lineSeparator());
+ }
+ }
+ }
+ try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("LOAD CONFIGURATION");
+ }
+ return fetchShowConfiguration();
+ } finally {
+ try (FileChannel fileChannel =
+ FileChannel.open(new File(confPath).toPath(),
StandardOpenOption.WRITE)) {
+ fileChannel.truncate(length);
+ }
+ }
+ }
+
+ private Map<String, String> fetchShowConfiguration() throws Exception {
+ Map<String, String> result = new HashMap<>();
+ try (ITableSession tableSessionConnection =
EnvFactory.getEnv().getTableSessionConnection()) {
+ SessionDataSet sessionDataSet =
+ tableSessionConnection.executeQueryStatement("show configuration");
+ SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+ while (iterator.next()) {
+ String name = iterator.getString(1);
+ String value = iterator.isNull(2) ? null : iterator.getString(2);
+ result.put(name, value);
+ }
+ }
+ return result;
+ }
+
+ private static void assertPositiveNonZero(Map<String, String> configMap,
String key) {
+ String value = configMap.get(key);
+ Assert.assertNotNull("show configuration is missing key: " + key, value);
+ long parsed = Long.parseLong(value);
+ Assert.assertTrue(
+ key + " should display a positive effective value, but was " + value,
parsed > 0);
+ }
}
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 ddbceab5cd7..3544f686624 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
@@ -1236,6 +1236,11 @@ public class IoTDBDescriptor {
if (maxSubTaskNumForInformationTableScan > 0) {
conf.setMaxSubTaskNumForInformationTableScan(maxSubTaskNumForInformationTableScan);
}
+
+ // Reflect the in-memory effective values (which the setters above may
have rewritten) into
+ // lastAppliedProperties, so that `show configuration` displays effective
values rather than
+ // the raw config-file values.
+ overlayEffectiveConfigurationValues();
}
private void loadFixedSizeLimitForQuery(
@@ -2344,6 +2349,9 @@ public class IoTDBDescriptor {
}
ConfigurationFileUtils.updateAppliedProperties(properties, true);
+ // Overwrite the keys whose setters above may have rewritten, so `show
configuration`
+ // displays the effective values rather than the raw file values.
+ overlayEffectiveConfigurationValues();
} catch (Exception e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
@@ -2353,6 +2361,31 @@ public class IoTDBDescriptor {
}
}
+ // `show configuration` (table model) renders
ConfigurationFileUtils.getAppliedProperties().
+ // That map is populated from the raw config-file values, but several
hot-reloaded parameters
+ // have setters that rewrite the loaded value before it takes effect, e.g.:
+ // - `if (x > 0) setX(x)` skips non-positive values (keeps the
previous/default value);
+ // - loadFixedSizeLimitForQuery rewrites `<=0` to a computed default.
+ // For those keys the displayed value would otherwise diverge from the
effective one. This
+ // method overwrites them with the post-setter effective value. It is
invoked after the setters
+ // in both the startup (loadProperties) and hot-reload
(loadHotModifiedProps) paths, so that
+ // local *and* remote `show configuration` (which reads each node's own map
over RPC) stay
+ // correct.
+ private void overlayEffectiveConfigurationValues() {
+ ConfigurationFileUtils.updateAppliedProperties(
+ "cte_buffer_size_in_bytes",
Long.toString(commonConfig.getCteBufferSize()));
+ ConfigurationFileUtils.updateAppliedProperties(
+ "max_rows_in_cte_buffer",
Integer.toString(commonConfig.getMaxRowsInCteBuffer()));
+ ConfigurationFileUtils.updateAppliedProperties(
+ "max_sub_task_num_for_information_table_scan",
+ Integer.toString(conf.getMaxSubTaskNumForInformationTableScan()));
+ ConfigurationFileUtils.updateAppliedProperties(
+ "sort_buffer_size_in_bytes",
+ Long.toString(commonDescriptor.getConfig().getSortBufferSize()));
+ ConfigurationFileUtils.updateAppliedProperties(
+ "mods_cache_size_limit_per_fi_in_bytes",
Long.toString(conf.getModsCacheSizeLimitPerFI()));
+ }
+
private void loadQuerySampleThroughput(TrimProperties properties) throws
IOException {
String querySamplingRateLimitNumber =
properties.getProperty(