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 962957f4f02e2..2dee987cb2c4f 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.commons.utils.TestOnly; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.CompactionUtils; import org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.writer.AbstractCompactionWriter; @@ -34,7 +35,6 @@ import org.apache.tsfile.encrypt.EncryptParameter; import java.io.IOException; -import java.nio.file.Files; import java.util.Collections; import java.util.List; @@ -83,7 +83,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 ArrayDeviceTimeIndex) { targetFile.setTimeIndex(timeIndex); @@ -91,9 +91,10 @@ private void prepareTargetFile() throws IOException { targetFile.setTimeIndex(CompactionUtils.buildDeviceTimeIndex(seqSourceFile)); } if (seqSourceFile.anyModFileExists()) { - Files.createLink( + FileUtils.createLink( seqSourceFile.getCompactionModFile().getFile().toPath(), - seqSourceFile.getExclusiveModFile().getFile().toPath()); + seqSourceFile.getExclusiveModFile().getFile().toPath(), + true); } } 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 dd8fb2b8e239b..b3f77c9214e53 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.i18n.StorageEngineMessages; import org.apache.iotdb.db.service.metrics.FileMetrics; @@ -221,10 +222,11 @@ 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); unseqFileToInsert.linkModFile(targetFile); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/v1/ModificationFileV1.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/v1/ModificationFileV1.java index d17a5b50c2e39..0d73a0b27c022 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/v1/ModificationFileV1.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/v1/ModificationFileV1.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.storageengine.dataregion.modification.v1; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.db.i18n.StorageEngineMessages; import org.apache.iotdb.db.storageengine.dataregion.modification.v1.io.LocalTextModificationAccessor; import org.apache.iotdb.db.storageengine.dataregion.modification.v1.io.ModificationReader; @@ -181,7 +182,7 @@ public ModificationFileV1 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 ModificationFileV1(hardlink.getAbsolutePath()); } catch (FileAlreadyExistsException e) { // retry a different name if the file is already created diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java index 439286288d623..3059d64ff7f78 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java @@ -26,6 +26,7 @@ import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.commons.pipe.datastructure.resource.PersistentResource; import org.apache.iotdb.commons.utils.CommonDateTimeUtils; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.commons.utils.TestOnly; import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; @@ -74,7 +75,6 @@ import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -407,10 +407,11 @@ public boolean anyModFileExists() { } public void link(TsFileResource target) throws IOException { - Files.createLink(target.getTsFile().toPath(), this.getTsFile().toPath()); - Files.createLink( + FileUtils.createLink(target.getTsFile().toPath(), this.getTsFile().toPath(), true); + FileUtils.createLink( new File(target.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath(), - new File(this.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath()); + new File(this.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).toPath(), + true); linkModFile(target); } @@ -422,8 +423,8 @@ public void linkModFile(TsFileResource target) throws IOException { try { if (sourceModFile.exists()) { // inherit modifications from the source file - Files.createLink( - targetModsFile.toPath(), ModificationFile.getExclusiveMods(getTsFile()).toPath()); + FileUtils.createLink( + targetModsFile.toPath(), ModificationFile.getExclusiveMods(getTsFile()).toPath(), true); } // ensure that new modifications will be written into the target file targetModsFileObject = new ModificationFile(targetModsFile, true); 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 be99503a3c9ef..3661e1d91cab8 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 @@ -89,6 +89,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); }