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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6fcbaddc0d6 Add copy fallback for compaction hard links (#18045)
6fcbaddc0d6 is described below

commit 6fcbaddc0d6d9877472b4088111c2bebe00c265b
Author: shuwenwei <[email protected]>
AuthorDate: Tue Jun 30 15:31:00 2026 +0800

    Add copy fallback for compaction hard links (#18045)
    
    * Add copy fallback for compaction hard links
    
    * Simplify create link fallback handling
    
    * fix compilation error
---
 .../impl/RepairUnsortedFileCompactionPerformer.java     |  9 +++++----
 .../execute/task/InsertionCrossSpaceCompactionTask.java |  8 +++++---
 .../dataregion/modification/v1/ModificationFileV1.java  |  3 ++-
 .../storageengine/dataregion/tsfile/TsFileResource.java | 13 +++++++------
 .../java/org/apache/iotdb/commons/utils/FileUtils.java  | 17 +++++++++++++++++
 5 files changed, 36 insertions(+), 14 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 962957f4f02..2dee987cb2c 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.iotdb.db.utils.EncryptDBUtils;
 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 @@ 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 ArrayDeviceTimeIndex) {
       targetFile.setTimeIndex(timeIndex);
@@ -91,9 +91,10 @@ public class RepairUnsortedFileCompactionPerformer extends 
ReadPointCompactionPe
       
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 dd8fb2b8e23..b3f77c9214e 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 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);
 
     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 d17a5b50c2e..0d73a0b27c0 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 class ModificationFileV1 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 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 439286288d6..3059d64ff7f 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.IFullPath;
 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.IOException;
 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 class TsFileResource implements 
PersistentResource, Cloneable {
   }
 
   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 class TsFileResource implements PersistentResource, 
Cloneable {
     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 be99503a3c9..3661e1d91ca 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 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