Skip to content

Commit 3ea1fc6

Browse files
authored
Delete empty TsFile sidecars after LOAD (#18599)
When LOAD skips an empty TsFile with on-success=delete, also remove its resource and mods files, and add an integration test covering the deletion.
1 parent 510c8cd commit 3ea1fc6

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.apache.iotdb.db.it.utils.TestUtils;
2626
import org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
2727
import org.apache.iotdb.db.storageengine.dataregion.modification.TreeDeletionEntry;
28+
import org.apache.iotdb.db.storageengine.dataregion.modification.v1.ModificationFileV1;
29+
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
2830
import org.apache.iotdb.it.env.EnvFactory;
2931
import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
3032
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -1010,6 +1012,31 @@ public void testLoadWithEmptyTsFile() throws Exception {
10101012
}
10111013
}
10121014

1015+
@Test
1016+
public void testDeleteEmptyTsFileAfterLoad() throws Exception {
1017+
final File tsFile = new File(tmpDir, "empty-1-0-0-0.tsfile");
1018+
try (final TsFileGenerator ignored = new TsFileGenerator(tsFile)) {}
1019+
1020+
final File resourceFile = new File(tsFile.getAbsolutePath() + TsFileResource.RESOURCE_SUFFIX);
1021+
final File modsFile = ModificationFile.getExclusiveMods(tsFile);
1022+
final File modsV1File = new File(tsFile.getAbsolutePath() + ModificationFileV1.FILE_SUFFIX);
1023+
1024+
Assert.assertTrue(resourceFile.createNewFile());
1025+
Assert.assertTrue(modsFile.createNewFile());
1026+
Assert.assertTrue(modsV1File.createNewFile());
1027+
1028+
try (final Connection connection = EnvFactory.getEnv().getConnection();
1029+
final Statement statement = connection.createStatement()) {
1030+
statement.execute(
1031+
String.format("load \"%s\" with ('on-success'='delete')", tsFile.getAbsolutePath()));
1032+
1033+
Assert.assertFalse(tsFile.exists());
1034+
Assert.assertFalse(resourceFile.exists());
1035+
Assert.assertFalse(modsFile.exists());
1036+
Assert.assertFalse(modsV1File.exists());
1037+
}
1038+
}
1039+
10131040
@Test
10141041
public void testAsyncLoadKeepsSameNamedTsFilesWithModsIsolated() throws Exception {
10151042
registerSchema();

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzer.java‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.iotdb.commons.queryengine.common.SessionInfo;
2727
import org.apache.iotdb.commons.queryengine.common.SqlDialect;
2828
import org.apache.iotdb.commons.queryengine.utils.TimestampPrecisionUtils;
29+
import org.apache.iotdb.commons.utils.RetryUtils;
2930
import org.apache.iotdb.db.conf.IoTDBDescriptor;
3031
import org.apache.iotdb.db.exception.load.LoadAnalyzeException;
3132
import org.apache.iotdb.db.exception.load.LoadAnalyzeInvalidPathException;
@@ -43,6 +44,7 @@
4344
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
4445
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LoadTsFile;
4546
import org.apache.iotdb.db.queryengine.plan.statement.crud.LoadTsFileStatement;
47+
import org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
4648
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
4749
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceStatus;
4850
import org.apache.iotdb.db.storageengine.dataregion.utils.TsFileResourceUtils;
@@ -69,6 +71,7 @@
6971
import java.io.FileNotFoundException;
7072
import java.io.IOException;
7173
import java.nio.BufferUnderflowException;
74+
import java.nio.file.Files;
7275
import java.util.ArrayList;
7376
import java.util.Arrays;
7477
import java.util.Collections;
@@ -490,14 +493,29 @@ && handleSingleMiniFile(i)) {
490493
DataNodeQueryMessages.EMPTY_FILE_DETECTED_WILL_SKIP_LOADING_THIS_FILE,
491494
tsFile.getAbsolutePath());
492495
if (isDeleteAfterLoad) {
493-
org.apache.iotdb.commons.utils.FileUtils.deleteFileIfExist(tsFile);
496+
deleteFile(tsFile);
497+
deleteFile(new File(LoadUtil.getTsFileResourcePath(tsFile.getAbsolutePath())));
498+
deleteFile(ModificationFile.getExclusiveMods(tsFile));
499+
deleteFile(new File(LoadUtil.getTsFileModsV1Path(tsFile.getAbsolutePath())));
494500
}
495501
} finally {
496502
// reset the session info to the original one
497503
context.setSession(sessionInfo);
498504
}
499505
}
500506

507+
private void deleteFile(final File file) {
508+
try {
509+
RetryUtils.retryOnException(
510+
() -> {
511+
Files.deleteIfExists(file.toPath());
512+
return null;
513+
});
514+
} catch (final Exception e) {
515+
LOGGER.warn(DataNodeQueryMessages.DELETE_AFTER_LOADING_ERROR, file, e);
516+
}
517+
}
518+
501519
private boolean handleSingleMiniFile(final int i) throws FileNotFoundException {
502520
final long startTime = System.nanoTime();
503521
try {

0 commit comments

Comments
 (0)