Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,6 +42,8 @@
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})
Expand Down Expand Up @@ -82,4 +86,94 @@ public void loadConfiguration() throws IOException {
}
}
}

// `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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@
loadFixedSizeLimitForQuery(
properties,
"sort_buffer_size_in_bytes",
(v) -> {

Check failure on line 1054 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "sort_buffer_size_in_bytes" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQv&open=AZ8nNaoWXO-nRr9hsEQv&pullRequest=18108
commonDescriptor.getConfig().setSortBufferSize(v);
});

Expand All @@ -1060,7 +1060,7 @@
Long.parseLong(
properties.getProperty(
"cte_buffer_size_in_bytes", Long.toString(commonConfig.getCteBufferSize())));
if (cteBufferSizeInBytes > 0) {

Check failure on line 1063 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "cte_buffer_size_in_bytes" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQt&open=AZ8nNaoWXO-nRr9hsEQt&pullRequest=18108
commonConfig.setCteBufferSize(cteBufferSizeInBytes);
}

Expand All @@ -1069,13 +1069,13 @@
Integer.parseInt(
properties.getProperty(
"max_rows_in_cte_buffer", Integer.toString(commonConfig.getMaxRowsInCteBuffer())));
if (maxRowsInCteBuffer > 0) {

Check failure on line 1072 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "max_rows_in_cte_buffer" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQs&open=AZ8nNaoWXO-nRr9hsEQs&pullRequest=18108
commonConfig.setMaxRowsInCteBuffer(maxRowsInCteBuffer);
}

loadFixedSizeLimitForQuery(
properties, "mods_cache_size_limit_per_fi_in_bytes", conf::setModsCacheSizeLimitPerFI);

Check failure on line 1078 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "mods_cache_size_limit_per_fi_in_bytes" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQu&open=AZ8nNaoWXO-nRr9hsEQu&pullRequest=18108
// tmp filePath for sort operator
conf.setSortTmpDir(properties.getProperty("sort_tmp_dir", conf.getSortTmpDir()));

Expand Down Expand Up @@ -1228,10 +1228,15 @@
Integer.parseInt(
properties.getProperty(
"max_sub_task_num_for_information_table_scan",
Integer.toString(conf.getMaxSubTaskNumForInformationTableScan())));

Check failure on line 1231 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "max_sub_task_num_for_information_table_scan" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQw&open=AZ8nNaoWXO-nRr9hsEQw&pullRequest=18108
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(
Expand Down Expand Up @@ -2333,6 +2338,9 @@
}

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();
Expand All @@ -2342,6 +2350,31 @@
}
}

// `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() {

Check warning on line 2363 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ8nNaoWXO-nRr9hsEQx&open=AZ8nNaoWXO-nRr9hsEQx&pullRequest=18108
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(
Expand Down
Loading