diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/performer/impl/RepairUnsortedFileCompactionPerformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/performer/impl/RepairUnsortedFileCompactionPerformer.java index 18e9ef24df2d8..534ea471ffa40 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/performer/impl/RepairUnsortedFileCompactionPerformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/performer/impl/RepairUnsortedFileCompactionPerformer.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.impl; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.CompactionUtils; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.writer.AbstractCompactionWriter; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.writer.RepairUnsortedFileCompactionWriter; @@ -31,7 +32,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.Collections; import java.util.List; @@ -74,7 +74,7 @@ protected QueryDataSource initQueryDataSource() { private void prepareTargetFile() throws IOException { TsFileResource seqSourceFile = seqFiles.get(0); TsFileResource targetFile = targetFiles.get(0); - Files.createLink(targetFile.getTsFile().toPath(), seqSourceFile.getTsFile().toPath()); + FileUtils.createLink(targetFile.getTsFile().toPath(), seqSourceFile.getTsFile().toPath(), true); ITimeIndex timeIndex = seqSourceFile.getTimeIndex(); if (timeIndex instanceof DeviceTimeIndex) { targetFile.setTimeIndex(timeIndex); @@ -82,9 +82,10 @@ private void prepareTargetFile() throws IOException { targetFile.setTimeIndex(CompactionUtils.buildDeviceTimeIndex(seqSourceFile)); } if (seqSourceFile.modFileExists()) { - Files.createLink( + FileUtils.createLink( new File(seqSourceFile.getCompactionModFile().getFilePath()).toPath(), - new File(seqSourceFile.getModFile().getFilePath()).toPath()); + new File(seqSourceFile.getModFile().getFilePath()).toPath(), + true); } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java index 77627579252f3..434c42be5ce11 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.commons.utils.TestOnly; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.exception.DiskSpaceInsufficientException; @@ -443,14 +444,16 @@ protected void prepareTargetFiles() throws IOException { for (int i = 0; i < filesView.renamedTargetFiles.size(); i++) { TsFileResource oldFile = filesView.skippedSourceFiles.get(i); TsFileResource newFile = filesView.renamedTargetFiles.get(i); - Files.createLink(newFile.getTsFile().toPath(), oldFile.getTsFile().toPath()); - Files.createLink( + FileUtils.createLink(newFile.getTsFile().toPath(), oldFile.getTsFile().toPath(), true); + FileUtils.createLink( new File(newFile.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath(), - new File(oldFile.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath()); + new File(oldFile.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath(), + true); if (oldFile.modFileExists()) { - Files.createLink( + FileUtils.createLink( new File(newFile.getTsFilePath() + ModificationFile.FILE_SUFFIX).toPath(), - new File(oldFile.getTsFilePath() + ModificationFile.FILE_SUFFIX).toPath()); + new File(oldFile.getTsFilePath() + ModificationFile.FILE_SUFFIX).toPath(), + true); } newFile.deserialize(); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java index 992b5406708e8..8b242feb64929 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.service.metrics.FileMetrics; import org.apache.iotdb.db.storageengine.dataregion.compaction.constant.CompactionTaskType; @@ -218,14 +219,16 @@ public File generateTargetFile() throws IOException { private void prepareTargetFiles() throws IOException { File sourceTsFile = unseqFileToInsert.getTsFile(); File targetTsFile = targetFile.getTsFile(); - Files.createLink(targetTsFile.toPath(), sourceTsFile.toPath()); - Files.createLink( + FileUtils.createLink(targetTsFile.toPath(), sourceTsFile.toPath(), true); + FileUtils.createLink( new File(targetTsFile.getPath() + TsFileResource.RESOURCE_SUFFIX).toPath(), - new File(sourceTsFile.getPath() + TsFileResource.RESOURCE_SUFFIX).toPath()); + new File(sourceTsFile.getPath() + TsFileResource.RESOURCE_SUFFIX).toPath(), + true); if (unseqFileToInsert.getModFile().exists()) { - Files.createLink( + FileUtils.createLink( new File(targetTsFile.getPath() + ModificationFile.FILE_SUFFIX).toPath(), - new File(sourceTsFile.getPath() + ModificationFile.FILE_SUFFIX).toPath()); + new File(sourceTsFile.getPath() + ModificationFile.FILE_SUFFIX).toPath(), + true); } targetFile.setProgressIndex(unseqFileToInsert.getMaxProgressIndex()); targetFile.deserialize(); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/RepairUnsortedFileCompactionTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/RepairUnsortedFileCompactionTask.java index f43bd7767b2c8..0cc773101d1e2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/RepairUnsortedFileCompactionTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/RepairUnsortedFileCompactionTask.java @@ -20,6 +20,7 @@ package org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task; import org.apache.iotdb.commons.conf.IoTDBConstant; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.db.storageengine.dataregion.compaction.constant.CompactionTaskType; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.impl.RepairUnsortedFileCompactionPerformer; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.CompactionUtils; @@ -35,7 +36,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.CountDownLatch; @@ -169,9 +169,10 @@ protected void prepareTargetFiles() throws IOException { filesView.sourceFilesInCompactionPerformer, filesView.targetFilesInPerformer); } else { if (sourceFile.modFileExists()) { - Files.createLink( + FileUtils.createLink( new File(filesView.targetFilesInPerformer.get(0).getModFile().getFilePath()).toPath(), - new File(sourceFile.getModFile().getFilePath()).toPath()); + new File(sourceFile.getModFile().getFilePath()).toPath(), + true); } } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java index 6489c7e52999f..bab214c5974dd 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.storageengine.dataregion.modification; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.db.storageengine.dataregion.modification.io.LocalTextModificationAccessor; import org.apache.iotdb.db.storageengine.dataregion.modification.io.ModificationReader; import org.apache.iotdb.db.storageengine.dataregion.modification.io.ModificationWriter; @@ -180,7 +181,7 @@ public ModificationFile createHardlink() { File hardlink = new File(filePath + hardlinkSuffix); try { - Files.createLink(Paths.get(hardlink.getAbsolutePath()), Paths.get(filePath)); + FileUtils.createLink(Paths.get(hardlink.getAbsolutePath()), Paths.get(filePath), true); return new ModificationFile(hardlink.getAbsolutePath()); } catch (FileAlreadyExistsException e) { // retry a different name if the file is already created diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java index 557adf43f6274..01232f9237ab2 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java @@ -70,6 +70,23 @@ public static boolean deleteFileIfExist(File file) { } } + public static void createLink(Path link, Path existing, boolean fallBackToCopy) + throws IOException { + try { + Files.createLink(link, existing); + } catch (IOException | UnsupportedOperationException e) { + if (!fallBackToCopy) { + throw e; + } + try { + Files.copy(existing, link); + } catch (IOException copyException) { + copyException.addSuppressed(e); + throw copyException; + } + } + } + public static void deleteFileOrDirectory(File file) { deleteFileOrDirectory(file, false); }