From 95d7335c6ea24afd08aff57d98de285a0b1b8c5d Mon Sep 17 00:00:00 2001 From: luoluoyuyu Date: Fri, 6 Nov 2026 17:13:48 +0800 Subject: [PATCH] Scope the TsFile scan of the load-storage IT to its own database IoTDBLoadStorageTsFileWithCompactionIT walked the whole DataNode data directory and required every TsFile below it to carry the table schema of table t1, and the TsFile counting helpers were built on the same scan. That directory is shared by every database of the node. Internal databases that store system records are tree-model databases, whose TsFiles legitimately have an empty table schema map, so the assertion fails with TsFile has no schema entry for table t1: {} as soon as the node holds such a database (observed on a downstream distribution that records the password history of "root" in root.__audit). The same files also polluted the counting helpers: "two TsFiles before compaction" could be satisfied by a single data file, and "exactly one TsFile after compaction" could never hold. Restrict every scan to /{sequence,unsequence}/load_storage_db, keep the assertions unchanged, and name the offending file in the failure messages. --- ...oTDBLoadStorageTsFileWithCompactionIT.java | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadStorageTsFileWithCompactionIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadStorageTsFileWithCompactionIT.java index bb8c79b921b1..4541fdd8c773 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadStorageTsFileWithCompactionIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadStorageTsFileWithCompactionIT.java @@ -19,6 +19,7 @@ package org.apache.iotdb.relational.it.db.it; +import org.apache.iotdb.commons.conf.IoTDBConstant; import org.apache.iotdb.it.env.MultiEnvFactory; import org.apache.iotdb.it.framework.IoTDBTestRunner; import org.apache.iotdb.itbase.category.MultiClusterIT2DualTableManualBasic; @@ -44,10 +45,10 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import java.util.stream.Stream; @RunWith(IoTDBTestRunner.class) @@ -194,59 +195,67 @@ private static void assertTableSchemaRegistered(final Path tsFile) throws IOExce try (final TsFileSequenceReader reader = new TsFileSequenceReader(tsFile.toAbsolutePath().toString())) { final Map tableSchemaMap = reader.getTableSchemaMap(); - Assert.assertNotNull("TsFile has no table schema map", tableSchemaMap); + Assert.assertNotNull("TsFile " + tsFile + " has no table schema map", tableSchemaMap); Assert.assertTrue( - "TsFile has no schema entry for table " + TABLE + ": " + tableSchemaMap, + "TsFile " + tsFile + " has no schema entry for table " + TABLE + ": " + tableSchemaMap, tableSchemaMap.containsKey(TABLE)); Assert.assertFalse( - "The storage path must not synthesize a TIME column: " + tableSchemaMap.get(TABLE), + "The storage path must not synthesize a TIME column: " + tsFile, tableSchemaMap.get(TABLE).getColumnTypes().contains(ColumnCategory.TIME)); Assert.assertTrue( - "A table-model TsFile must carry the " + TABLE_MODEL_PROPERTY + " property", + "A table-model TsFile must carry the " + + TABLE_MODEL_PROPERTY + + " property, but " + + tsFile + + " does not", reader.readFileMetadata().getTsFileProperties().containsKey(TABLE_MODEL_PROPERTY)); } } private static void assertAllTsFilesHaveTableSchema(final BaseEnv env) throws IOException { - final Path dataPath = Paths.get(env.getDataNodeWrapper(0).getDataPath()); - try (final Stream paths = Files.walk(dataPath)) { - final List tsFiles = - paths - .filter(Files::isRegularFile) - .filter(path -> path.getFileName().toString().endsWith(TsFileConstant.TSFILE_SUFFIX)) - .collect(Collectors.toList()); - Assert.assertFalse("No TsFile was produced", tsFiles.isEmpty()); - for (final Path tsFile : tsFiles) { - assertTableSchemaRegistered(tsFile); - } + final List tsFiles = listDatabaseTsFiles(env); + Assert.assertFalse("No TsFile was produced for database " + DATABASE, tsFiles.isEmpty()); + for (final Path tsFile : tsFiles) { + assertTableSchemaRegistered(tsFile); } } private static long countTsFiles(final BaseEnv env) throws IOException { - final Path dataPath = Paths.get(env.getDataNodeWrapper(0).getDataPath()); - if (!Files.exists(dataPath)) { - return 0; - } - try (final Stream paths = Files.walk(dataPath)) { - return paths - .filter(Files::isRegularFile) - .filter(path -> path.getFileName().toString().endsWith(TsFileConstant.TSFILE_SUFFIX)) - .count(); - } + return listDatabaseTsFiles(env).size(); } private static Path findSingleTsFile(final BaseEnv env) throws IOException { + final List tsFiles = listDatabaseTsFiles(env); + Assert.assertEquals( + "Expected exactly one compacted TsFile, but got " + tsFiles, 1, tsFiles.size()); + return tsFiles.get(0); + } + + /** + * Lists the TsFiles of the database owned by this test only. + * + *

The DataNode data directory is shared by every database of the node, including the internal + * ones that store system records. Those databases are tree-model databases whose TsFiles + * legitimately carry no table schema at all, so scanning the whole data directory would mix + * unrelated TsFiles into the table-schema assertions of this test. + */ + private static List listDatabaseTsFiles(final BaseEnv env) throws IOException { final Path dataPath = Paths.get(env.getDataNodeWrapper(0).getDataPath()); - try (final Stream paths = Files.walk(dataPath)) { - final List tsFiles = - paths - .filter(Files::isRegularFile) - .filter(path -> path.getFileName().toString().endsWith(TsFileConstant.TSFILE_SUFFIX)) - .collect(Collectors.toList()); - Assert.assertEquals( - "Expected exactly one compacted TsFile, but got " + tsFiles, 1, tsFiles.size()); - return tsFiles.get(0); + final List tsFiles = new ArrayList<>(); + for (final String folder : + new String[] {IoTDBConstant.SEQUENCE_FOLDER_NAME, IoTDBConstant.UNSEQUENCE_FOLDER_NAME}) { + final Path databaseDir = dataPath.resolve(folder).resolve(DATABASE); + if (!Files.isDirectory(databaseDir)) { + continue; + } + try (final Stream paths = Files.walk(databaseDir)) { + paths + .filter(Files::isRegularFile) + .filter(path -> path.getFileName().toString().endsWith(TsFileConstant.TSFILE_SUFFIX)) + .forEach(tsFiles::add); + } } + return tsFiles; } private static void deleteRecursively(final Path path) throws IOException {