Skip to content

Commit d3caec7

Browse files
committed
Test active load file group isolation
1 parent 5ca66d5 commit d3caec7

6 files changed

Lines changed: 73 additions & 0 deletions

File tree

integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
package org.apache.iotdb.db.it;
2121

2222
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
23+
import org.apache.iotdb.commons.path.MeasurementPath;
2324
import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
2425
import org.apache.iotdb.db.it.utils.TestUtils;
26+
import org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
27+
import org.apache.iotdb.db.storageengine.dataregion.modification.TreeDeletionEntry;
2528
import org.apache.iotdb.it.env.EnvFactory;
2629
import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
2730
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -985,6 +988,62 @@ public void testLoadWithEmptyTsFile() throws Exception {
985988
}
986989
}
987990

991+
@Test
992+
public void testAsyncLoadKeepsSameNamedTsFilesWithModsIsolated() throws Exception {
993+
registerSchema();
994+
995+
long expectedPointCount = 0;
996+
// Before each file group had its own transfer directory, these same-named TsFiles and mods
997+
// were renamed independently in one shared directory and could be paired with the wrong file.
998+
for (int i = 0; i < 2; i++) {
999+
final File sourceDir = new File(tmpDir, "source-" + i);
1000+
Assert.assertTrue(sourceDir.mkdirs());
1001+
try (final TsFileGenerator generator =
1002+
new TsFileGenerator(new File(sourceDir, "1-0-0-0.tsfile"))) {
1003+
generator.resetRandom(i);
1004+
generator.registerTimeseries(
1005+
SchemaConfig.DEVICE_0, Collections.singletonList(SchemaConfig.MEASUREMENT_00));
1006+
generator.generateData(SchemaConfig.DEVICE_0, 20, 1, false, TimeUnit.SECONDS.toMillis(i));
1007+
// Each group contributes 20 points and its own mods deletes exactly one. Losing either
1008+
// TsFile-to-mods pairing therefore leaves 39 points instead of the expected 38.
1009+
expectedPointCount += generator.getTotalNumber() - 1;
1010+
}
1011+
try (final ModificationFile modificationFile =
1012+
new ModificationFile(
1013+
new File(sourceDir, "1-0-0-0.tsfile" + ModificationFile.FILE_SUFFIX), false)) {
1014+
modificationFile.write(
1015+
new TreeDeletionEntry(
1016+
new MeasurementPath(
1017+
SchemaConfig.DEVICE_0, SchemaConfig.MEASUREMENT_00.getMeasurementName()),
1018+
TimeUnit.SECONDS.toMillis(i) + 1,
1019+
TimeUnit.SECONDS.toMillis(i) + 1));
1020+
}
1021+
}
1022+
1023+
try (final Connection connection = EnvFactory.getEnv().getConnection();
1024+
final Statement statement = connection.createStatement()) {
1025+
statement.execute(
1026+
String.format(
1027+
"load \"%s\" with ('async'='true','database-level'='2','on-success'='delete')",
1028+
tmpDir.getAbsolutePath()));
1029+
}
1030+
1031+
TestUtils.assertDataEventuallyOnEnv(
1032+
EnvFactory.getEnv(),
1033+
"select count("
1034+
+ SchemaConfig.MEASUREMENT_00.getMeasurementName()
1035+
+ ") from "
1036+
+ SchemaConfig.DEVICE_0,
1037+
Collections.singletonMap(
1038+
"count("
1039+
+ SchemaConfig.DEVICE_0
1040+
+ "."
1041+
+ SchemaConfig.MEASUREMENT_00.getMeasurementName()
1042+
+ ")",
1043+
Long.toString(expectedPointCount)),
1044+
30);
1045+
}
1046+
9881047
@Test
9891048
public void testLoadTsFileWithWrongTimestampPrecision() throws Exception {
9901049
try (final TsFileGenerator generator =

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/load/LoadTsFileNodeTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public void testLoadTsFilePieceNode() {
9797
public void testCleanContinuesAfterOneFileCannotBeDeleted() throws Exception {
9898
final File tempDir = Files.createTempDirectory("load-node-clean").toFile();
9999
try {
100+
// A non-empty directory at the TsFile path makes that deletion fail deterministically. The
101+
// companion cleanup must still continue instead of sharing the same try-catch block.
100102
final File tsFile = new File(tempDir, "1-0-0-0.tsfile");
101103
Assert.assertTrue(tsFile.mkdirs());
102104
Assert.assertTrue(new File(tsFile, "non-empty").createNewFile());

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/scheduler/load/LoadTsFileSchedulerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ public void testTsFileDataManagerClearReleasesCachedMemory() throws Exception {
142142
dataManagerConstructor.newInstance(
143143
mock(LoadTsFileScheduler.class), mock(LoadSingleTsFileNode.class), memoryBlock);
144144

145+
// Simulate data buffered before split or routing aborts. clear() is the last chance to return
146+
// this accounting to the shared LOAD memory block.
145147
final long cachedMemorySize = 128L;
146148
memoryBlock.addMemoryUsage(cachedMemorySize);
147149
final Field dataSizeField = dataManagerClass.getDeclaredField("dataSize");

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadDirScannerTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ public void tearDown() {
8080

8181
@Test
8282
public void testScanDeduplicatesTsFileAndCompanionFiles() throws Exception {
83+
// The recursive scanner sees all four paths, but every companion maps back to the same TsFile.
84+
// Enqueuing each path separately used to consume queue capacity and schedule duplicate loads.
8385
final File tsFile = createCompletedTsFile(pendingDir, "1-0-0-0.tsfile");
8486
Assert.assertTrue(
8587
new File(tsFile.getAbsolutePath() + TsFileResource.RESOURCE_SUFFIX).createNewFile());
@@ -106,6 +108,8 @@ public void testScanDeduplicatesTsFileAndCompanionFiles() throws Exception {
106108

107109
@Test
108110
public void testAttributeAndTransferDirectoriesDoNotImplyTableModel() throws Exception {
111+
// Async tree loads add attribute and per-handoff transfer directories below pending. These are
112+
// internal directories, not table database names inferred from a user-created subdirectory.
109113
final Map<String, String> attributes =
110114
ActiveLoadPathHelper.buildAttributes(null, 2, false, false, null, false, "test-user");
111115
final File attributeDir = ActiveLoadPathHelper.resolveTargetDir(pendingDir, attributes);

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadTsFileLoaderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ public void testStopClearsPendingFilesForRestart() throws Exception {
119119
Assert.assertTrue(pendingQueue.enqueue(tsFilePath, tempDir.getAbsolutePath(), false, false));
120120
Assert.assertTrue(loader.isFilePendingOrLoading(new File(tsFilePath)));
121121

122+
// A loader restart reuses this queue. Stale pending membership otherwise makes the scanner
123+
// believe the on-disk TsFile is already scheduled and it will never enqueue it again.
122124
loader.stop();
123125

124126
Assert.assertFalse(loader.isFilePendingOrLoading(new File(tsFilePath)));

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/load/util/LoadUtilTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public void tearDown() {
5959
public void testTransferFilesKeepsCompanionsTogetherAndDeletesSourcesAfterHandoff()
6060
throws Exception {
6161
final List<File> sourceFiles = createTsFileAndCompanions();
62+
// Existing same-named files represent a previous handoff. A new group must be isolated rather
63+
// than independently renaming the TsFile and companions in this shared target directory.
6264
for (final File sourceFile : sourceFiles) {
6365
Files.write(
6466
new File(targetDir, sourceFile.getName()).toPath(),
@@ -86,6 +88,8 @@ public void testTransferFilesKeepsCompanionsTogetherAndDeletesSourcesAfterHandof
8688
@Test
8789
public void testTransferFailureDoesNotDeleteSources() throws Exception {
8890
final List<File> sourceFiles = createTsFileAndCompanions();
91+
// A regular file cannot contain the temporary transfer directory, forcing handoff to fail
92+
// before ownership of any source file can be released.
8993
final File invalidTargetDir = new File(tempDir, "target-file");
9094
Assert.assertTrue(invalidTargetDir.createNewFile());
9195

0 commit comments

Comments
 (0)