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

jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new eb42ffbed2d [to dev/1.3] Add copy fallback for compaction hard links 
(#18083)
eb42ffbed2d is described below

commit eb42ffbed2dada25b0130526b0acb1e584c0e40d
Author: shuwenwei <[email protected]>
AuthorDate: Wed Jul 1 18:36:10 2026 +0800

    [to dev/1.3] Add copy fallback for compaction hard links (#18083)
    
    * Add copy fallback for compaction hard links
    
    * Simplify create link fallback handling
    
    * Replace remaining compaction hard links with FileUtils
    
    * Keep compaction recovery tests using direct hard links
    
    * spotless
    
    * fix compilation error
---
 .../impl/RepairUnsortedFileCompactionPerformer.java     |  9 +++++----
 .../execute/task/InnerSpaceCompactionTask.java          | 13 ++++++++-----
 .../execute/task/InsertionCrossSpaceCompactionTask.java | 13 ++++++++-----
 .../execute/task/RepairUnsortedFileCompactionTask.java  |  7 ++++---
 .../dataregion/modification/ModificationFile.java       |  3 ++-
 .../java/org/apache/iotdb/commons/utils/FileUtils.java  | 17 +++++++++++++++++
 6 files changed, 44 insertions(+), 18 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/InnerSpaceCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java
index 77627579252..434c42be5ce 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 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
     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 992b5406708..8b242feb649 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 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/compaction/execute/task/RepairUnsortedFileCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/RepairUnsortedFileCompactionTask.java
index f43bd7767b2..0cc773101d1 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 
org.apache.iotdb.db.storageengine.rescon.memory.SystemInfo;
 
 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 @@ public class RepairUnsortedFileCompactionTask extends 
InnerSpaceCompactionTask {
           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 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..01232f9237a 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 class FileUtils {
     }
   }
 
+  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);
   }

Reply via email to