This is an automated email from the ASF dual-hosted git repository.

shuwenwei pushed a commit to branch cp-pr-18045-dev-1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit e09546ec3507ca76f668664e5ac5d0c28490e398
Author: shuwenwei <[email protected]>
AuthorDate: Fri Jun 26 18:25:23 2026 +0800

    Add copy fallback for compaction hard links
---
 .../RepairUnsortedFileCompactionPerformer.java     |  9 ++++----
 .../task/InsertionCrossSpaceCompactionTask.java    | 14 ++++++-----
 .../dataregion/modification/ModificationFile.java  |  3 ++-
 .../org/apache/iotdb/commons/utils/FileUtils.java  | 27 ++++++++++++++++++++++
 4 files changed, 42 insertions(+), 11 deletions(-)

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 18e9ef24df2..534ea471ffa 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 
org.apache.iotdb.db.storageengine.rescon.memory.TsFileResourceManager;
 
 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 @@ public class RepairUnsortedFileCompactionPerformer extends 
ReadPointCompactionPe
   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 @@ public class RepairUnsortedFileCompactionPerformer extends 
ReadPointCompactionPe
       
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/InsertionCrossSpaceCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java
index 992b5406708..e4440ac32f9 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;
@@ -37,7 +38,6 @@ import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.generator.TsFileNameG
 
 import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -218,14 +218,16 @@ public class InsertionCrossSpaceCompactionTask extends 
AbstractCompactionTask {
   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/modification/ModificationFile.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java
index 6489c7e5299..bab214c5974 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 class ModificationFile implements AutoCloseable {
       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 557adf43f62..ee5bff42ad6 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,33 @@ public class FileUtils {
     }
   }
 
+  public static void createLink(Path link, Path existing, boolean 
fallBackToCopy)
+      throws IOException {
+    try {
+      Files.createLink(link, existing);
+    } catch (IOException e) {
+      if (!fallBackToCopy) {
+        throw e;
+      }
+      try {
+        Files.copy(existing, link);
+      } catch (IOException copyException) {
+        copyException.addSuppressed(e);
+        throw copyException;
+      }
+    } catch (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);
   }

Reply via email to