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

jiangtian 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 f8e24dc71eb Feature/retry on disk failure (#15676)
f8e24dc71eb is described below

commit f8e24dc71eb3838aa149158c70354d114e9e3952
Author: Hongzhi Gao <[email protected]>
AuthorDate: Thu Jul 3 18:40:06 2025 +0800

    Feature/retry on disk failure (#15676)
    
    * Skip faulty disk
    
    * fix some issues
    
    * Adjusted the log messages related to disk failures.
    
    * Adjusted the log messages related to disk failures.
    
    * Format code using Spotless
    
    * Added FolderManager.getNextWithRetry(Consumer folderConsumer)
    
    * fix ut failures
---
 .../receiver/protocol/IoTDBConfigNodeReceiver.java |  3 +
 .../iotdb/db/exception/load/LoadFileException.java |  4 ++
 .../connector/util/builder/PipeTsFileBuilder.java  | 40 +++++++-----
 .../pipeconsensus/PipeConsensusReceiver.java       | 75 +++++++++++-----------
 .../protocol/thrift/IoTDBDataNodeReceiver.java     |  5 ++
 .../dataregion/snapshot/SnapshotLoader.java        | 67 +++++++++++++------
 .../tsfile/generator/TsFileNameGenerator.java      | 63 ++++++++++--------
 .../allocation/AbstractNodeAllocationStrategy.java | 13 ++--
 .../db/storageengine/load/LoadTsFileManager.java   | 12 ++--
 .../storageengine/load/disk/ILoadDiskSelector.java |  3 +-
 .../InheritSystemMultiDisksStrategySelector.java   | 42 ++++++++----
 .../db/storageengine/load/disk/MinIOSelector.java  |  3 +-
 .../storageengine/rescon/disk/FolderManager.java   | 63 ++++++++++++++++++
 .../db/storageengine/rescon/disk/TierManager.java  |  4 ++
 .../rescon/disk/strategy/DirectoryStrategy.java    | 34 ++++++++++
 .../strategy/MaxDiskUsableSpaceFirstStrategy.java  |  3 +
 .../MinFolderOccupiedSpaceFirstStrategy.java       |  4 ++
 .../strategy/RandomOnDiskUsableSpaceStrategy.java  |  4 ++
 .../rescon/disk/strategy/SequenceStrategy.java     |  4 +-
 .../commons/pipe/receiver/IoTDBFileReceiver.java   | 66 ++++++++++---------
 .../apache/iotdb/commons/utils/JVMCommonUtils.java | 56 +++++++++-------
 21 files changed, 389 insertions(+), 179 deletions(-)

diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
index 9930f9f2707..6c177abbf86 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
@@ -1000,6 +1000,9 @@ public class IoTDBConfigNodeReceiver extends 
IoTDBFileReceiver {
     return 
ConfigNodeDescriptor.getInstance().getConf().getPipeReceiverFileDir();
   }
 
+  @Override
+  protected void markFileBaseDirStateAbnormal(String dir) {}
+
   @Override
   protected String getSenderHost() {
     final IClientSession session = SESSION_MANAGER.getCurrSession();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/load/LoadFileException.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/load/LoadFileException.java
index 0d1c4c53882..d681a24d029 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/load/LoadFileException.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/load/LoadFileException.java
@@ -31,4 +31,8 @@ public class LoadFileException extends IoTDBException {
   public LoadFileException(Exception exception) {
     super(exception, TSStatusCode.LOAD_FILE_ERROR.getStatusCode());
   }
+
+  public LoadFileException(String message, Exception exception) {
+    super(message, exception, TSStatusCode.LOAD_FILE_ERROR.getStatusCode());
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/connector/util/builder/PipeTsFileBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/connector/util/builder/PipeTsFileBuilder.java
index 8b97cafe4c8..873d55d2b7e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/connector/util/builder/PipeTsFileBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/connector/util/builder/PipeTsFileBuilder.java
@@ -81,27 +81,35 @@ public abstract class PipeTsFileBuilder {
         }
       }
     }
-
-    final File baseDir =
-        new File(FOLDER_MANAGER.get().getNextFolder(), 
Long.toString(currentBatchId.get()));
-    if (baseDir.exists()) {
-      FileUtils.deleteQuietly(baseDir);
-    }
-    if (!baseDir.exists() && !baseDir.mkdirs()) {
-      LOGGER.warn(
-          "Batch id = {}: Failed to create batch file dir {}.",
-          currentBatchId.get(),
-          baseDir.getPath());
+    synchronized (FOLDER_MANAGER) {
+      File baseDir =
+          FOLDER_MANAGER
+              .get()
+              .getNextWithRetry(
+                  folder -> {
+                    File dir = new File(folder, 
Long.toString(currentBatchId.get()));
+                    FileUtils.deleteQuietly(dir);
+                    if (dir.mkdirs()) {
+                      LOGGER.info(
+                          "Batch id = {}: Create batch dir successfully, batch 
file dir = {}.",
+                          currentBatchId.get(),
+                          dir.getPath());
+                      return dir;
+                    }
+                    LOGGER.warn(
+                        "Batch id = {}: Failed to create batch file dir {}.",
+                        currentBatchId.get(),
+                        dir.getPath());
+                    return null;
+                  });
+      if (baseDir != null) {
+        return baseDir;
+      }
       throw new PipeException(
           String.format(
               "Failed to create batch file dir %s. (Batch id = %s)",
               baseDir.getPath(), currentBatchId.get()));
     }
-    LOGGER.info(
-        "Batch id = {}: Create batch dir successfully, batch file dir = {}.",
-        currentBatchId.get(),
-        baseDir.getPath());
-    return baseDir;
   }
 
   public abstract void bufferTableModelTablet(String dataBase, Tablet tablet);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
index 4e5163a5bb0..82c39729dfd 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
@@ -1002,11 +1002,6 @@ public class PipeConsensusReceiver {
         tsFileWriter.getWritingFile().getPath());
   }
 
-  private String getReceiverFileBaseDir() throws 
DiskSpaceInsufficientException {
-    // Get next receiver file base dir by folder manager
-    return Objects.isNull(folderManager) ? null : 
folderManager.getNextFolder();
-  }
-
   private void initiateTsFileBufferFolder(List<String> receiverBaseDirsName) 
throws IOException {
     // initiate receiverFileDirs
     for (String receiverFileBaseDir : receiverBaseDirsName) {
@@ -1230,44 +1225,48 @@ public class PipeConsensusReceiver {
     }
 
     public void rollToNextWritingPath() throws IOException, 
DiskSpaceInsufficientException {
-      String receiverBasePath;
-      try {
-        receiverBasePath = getReceiverFileBaseDir();
-      } catch (Exception e) {
-        LOGGER.warn(
-            "Failed to init pipeConsensus receiver file folder manager because 
all disks of folders are full.",
-            e);
-        throw e;
-      }
-      if (Objects.isNull(receiverBasePath)) {
-        LOGGER.warn(
-            "PipeConsensus-PipeName-{}: Failed to get pipeConsensus receiver 
file base directory, because folderManager is null. May because the disk is 
full.",
-            consensusPipeName.toString());
-        throw new DiskSpaceInsufficientException(receiveDirs);
+      if (folderManager == null) {
+        throw new IOException(
+            String.format(
+                "PipeConsensus-PipeName-%s: Failed to create tsFileWriter-%d 
receiver file dir",
+                consensusPipeName, index));
       }
+      this.localWritingDir =
+          folderManager.getNextWithRetry(
+              receiverBasePath -> {
+                if (receiverBasePath == null) {
+                  LOGGER.warn(
+                      "PipeConsensus-PipeName-{}: Failed to get base 
directory", consensusPipeName);
+                  return null;
+                }
+                File writingDir = new File(receiverBasePath + File.separator + 
index);
+                deleteFileOrDirectoryIfExists(
+                    writingDir,
+                    String.format(
+                        "TsFileWriter-%s roll to new dir and delete last 
writing dir", index));
 
-      String localWritingDirPath = receiverBasePath + File.separator + index;
-      this.localWritingDir = new File(localWritingDirPath);
-      // Remove exists dir
-      deleteFileOrDirectoryIfExists(
-          this.localWritingDir,
-          String.format("TsFileWriter-%s roll to new dir and delete last 
writing dir", index));
-      if (!this.localWritingDir.mkdirs()) {
-        LOGGER.warn(
-            "PipeConsensus-PipeName-{}: Failed to create receiver 
tsFileWriter-{} file dir {}. May because authority or dir already exists etc.",
-            consensusPipeName,
-            index,
-            this.localWritingDir.getPath());
+                if (writingDir.mkdirs()) {
+                  LOGGER.info(
+                      "PipeConsensus-PipeName-{}: tsfileWriter-{} roll to 
writing path {}",
+                      consensusPipeName,
+                      index,
+                      writingDir.getPath());
+                  return writingDir;
+                }
+                LOGGER.warn(
+                    "PipeConsensus-PipeName-{}: Failed to create receiver 
tsFileWriter-{} file dir {}",
+                    consensusPipeName,
+                    index,
+                    writingDir.getPath());
+                return null;
+              });
+
+      if (this.localWritingDir == null) {
         throw new IOException(
             String.format(
-                "PipeConsensus-PipeName-%s: Failed to create tsFileWriter-%d 
receiver file dir %s. May because authority or dir already exists etc.",
-                consensusPipeName, index, this.localWritingDir.getPath()));
+                "PipeConsensus-PipeName-%s: Failed to create tsFileWriter-%d 
receiver file dir",
+                consensusPipeName, index));
       }
-      LOGGER.info(
-          "PipeConsensus-PipeName-{}: tsfileWriter-{} roll to writing path {}",
-          consensusPipeName,
-          index,
-          localWritingDirPath);
     }
 
     public File getLocalWritingDir() {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
index b8634f92b64..720ecfa76ac 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
@@ -508,6 +508,11 @@ public class IoTDBDataNodeReceiver extends 
IoTDBFileReceiver {
     return Objects.isNull(folderManager) ? null : 
folderManager.getNextFolder();
   }
 
+  @Override
+  protected void markFileBaseDirStateAbnormal(String dir) {
+    folderManager.updateFolderState(dir, FolderManager.FolderState.ABNORMAL);
+  }
+
   @Override
   protected String getSenderHost() {
     final IClientSession session = SESSION_MANAGER.getCurrSession();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
index 57ae347b48b..5c5c8e490ce 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
@@ -288,28 +288,57 @@ public class SnapshotLoader {
     Map<String, String> fileTarget = new HashMap<>();
     for (File file : files) {
       String fileKey = file.getName().split("\\.")[0];
-      String dataDir;
-      if (fileTarget.containsKey(fileKey)) {
-        dataDir = fileTarget.get(fileKey);
-      } else {
-        dataDir = folderManager.getNextFolder();
-        fileTarget.put(fileKey, dataDir);
-      }
-      File targetFile =
-          new File(dataDir + File.separator + targetSuffix + File.separator + 
file.getName());
-      if (!targetFile.getParentFile().exists() && 
!targetFile.getParentFile().mkdirs()) {
+      String dataDir = fileTarget.get(fileKey);
+
+      try {
+        folderManager.getNextWithRetry(
+            currentDataDir -> {
+              String effectiveDir = (dataDir != null) ? dataDir : 
currentDataDir;
+              File targetFile =
+                  new File(
+                      effectiveDir
+                          + File.separator
+                          + targetSuffix
+                          + File.separator
+                          + file.getName());
+
+              try {
+                if (!targetFile.getParentFile().exists() && 
!targetFile.getParentFile().mkdirs()) {
+                  throw new IOException(
+                      String.format(
+                          "Cannot create directory %s",
+                          targetFile.getParentFile().getAbsolutePath()));
+                }
+
+                try {
+                  Files.createLink(targetFile.toPath(), file.toPath());
+                  LOGGER.debug("Created hard link from {} to {}", file, 
targetFile);
+                  return targetFile;
+                } catch (IOException e) {
+                  LOGGER.info(
+                      "Cannot create link from {} to {}, fallback to copy", 
file, targetFile);
+                }
+
+                Files.copy(file.toPath(), targetFile.toPath());
+                fileTarget.put(fileKey, effectiveDir);
+                return targetFile;
+              } catch (Exception e) {
+                LOGGER.warn(
+                    "Failed to process file {} in dir {}: {}",
+                    file.getName(),
+                    effectiveDir,
+                    e.getMessage(),
+                    e);
+                throw e;
+              }
+            });
+      } catch (Exception e) {
         throw new IOException(
             String.format(
-                "Cannot create directory %s", 
targetFile.getParentFile().getAbsolutePath()));
+                "Failed to process file after retries. Source: %s, Target 
suffix: %s",
+                file.getAbsolutePath(), targetSuffix),
+            e);
       }
-      try {
-        Files.createLink(targetFile.toPath(), file.toPath());
-        continue;
-      } catch (IOException e) {
-        LOGGER.info("Cannot create link from {} to {}, try to copy it", file, 
targetFile);
-      }
-
-      Files.copy(file.toPath(), targetFile.toPath());
     }
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/generator/TsFileNameGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/generator/TsFileNameGenerator.java
index ea408883553..ca0088479e9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/generator/TsFileNameGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/generator/TsFileNameGenerator.java
@@ -24,11 +24,14 @@ import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
 import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceStatus;
+import org.apache.iotdb.db.storageengine.rescon.disk.FolderManager;
 import org.apache.iotdb.db.storageengine.rescon.disk.TierManager;
 
 import org.apache.tsfile.common.constant.TsFileConstant;
 import org.apache.tsfile.fileSystem.FSFactoryProducer;
 import org.apache.tsfile.fileSystem.fsFactory.FSFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
@@ -43,6 +46,7 @@ import static 
org.apache.tsfile.common.constant.TsFileConstant.TSFILE_SUFFIX;
 public class TsFileNameGenerator {
 
   private static FSFactory fsFactory = FSFactoryProducer.getFSFactory();
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(TsFileNameGenerator.class);
 
   public static String generateNewTsFilePath(
       String tsFileDir,
@@ -65,7 +69,7 @@ public class TsFileNameGenerator {
       long version,
       int innerSpaceCompactionCount,
       int crossSpaceCompactionCount)
-      throws DiskSpaceInsufficientException {
+      throws DiskSpaceInsufficientException, IOException {
     return generateNewTsFilePathWithMkdir(
         sequence,
         logicalStorageGroup,
@@ -90,33 +94,36 @@ public class TsFileNameGenerator {
       int crossSpaceCompactionCount,
       int tierLevel,
       String customSuffix)
-      throws DiskSpaceInsufficientException {
-    String tsFileDir =
-        generateTsFileDir(
-            sequence, logicalStorageGroup, virtualStorageGroup, 
timePartitionId, tierLevel);
-    fsFactory.getFile(tsFileDir).mkdirs();
-    return tsFileDir
-        + File.separator
-        + generateNewTsFileName(
-            time, version, innerSpaceCompactionCount, 
crossSpaceCompactionCount, customSuffix);
-  }
-
-  public static String generateTsFileDir(
-      boolean sequence,
-      String logicalStorageGroup,
-      String virtualStorageGroup,
-      long timePartitionId,
-      int tierLevel)
-      throws DiskSpaceInsufficientException {
-    TierManager tierManager = TierManager.getInstance();
-    String baseDir = tierManager.getNextFolderForTsFile(tierLevel, sequence);
-    return baseDir
-        + File.separator
-        + logicalStorageGroup
-        + File.separator
-        + virtualStorageGroup
-        + File.separator
-        + timePartitionId;
+      throws DiskSpaceInsufficientException, IOException {
+    FolderManager folderManager = 
TierManager.getInstance().getFolderManager(tierLevel, sequence);
+    try {
+      return folderManager.getNextWithRetry(
+          baseDir -> {
+            String tsFileDir =
+                baseDir
+                    + File.separator
+                    + logicalStorageGroup
+                    + File.separator
+                    + virtualStorageGroup
+                    + File.separator
+                    + timePartitionId;
+            fsFactory.getFile(tsFileDir).mkdirs();
+            return tsFileDir
+                + File.separator
+                + generateNewTsFileName(
+                    time,
+                    version,
+                    innerSpaceCompactionCount,
+                    crossSpaceCompactionCount,
+                    customSuffix);
+          });
+    } catch (DiskSpaceInsufficientException e) {
+      LOGGER.error("All disks are full, cannot create tsfile directory", e);
+      throw new IOException("Disk space insufficient", e);
+    } catch (Exception e) {
+      LOGGER.warn("Failed to create tsfile directory after retries", e);
+      throw new IOException("Failed to create directory after retries", e);
+    }
   }
 
   public static String generateNewTsFileName(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/allocation/AbstractNodeAllocationStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/allocation/AbstractNodeAllocationStrategy.java
index e98086e5146..119f262ea66 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/allocation/AbstractNodeAllocationStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/allocation/AbstractNodeAllocationStrategy.java
@@ -56,17 +56,18 @@ public abstract class AbstractNodeAllocationStrategy 
implements NodeAllocationSt
   }
 
   protected IWALNode createWALNode(String identifier) {
-    String folder;
-    // get wal folder
     try {
-      folder = folderManager.getNextFolder();
+      return folderManager.getNextWithRetry(
+          folder -> new WALNode(identifier, folder + File.separator + 
identifier));
     } catch (DiskSpaceInsufficientException e) {
       logger.error("Fail to create wal node because all disks of wal folders 
are full.", e);
       return WALFakeNode.getFailureInstance(e);
+    } catch (Exception e) {
+      logger.warn("Failed to create WAL node after retries for identifier: " + 
identifier, e);
+      return WALFakeNode.getFailureInstance(
+          new IOException(
+              "Failed to create WAL node after retries for identifier: " + 
identifier, e));
     }
-    folder = folder + File.separator + identifier;
-    // create new wal node
-    return createWALNode(identifier, folder);
   }
 
   protected IWALNode createWALNode(String identifier, String folder) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
index 390dc984696..a0cdebdf030 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
@@ -222,12 +222,14 @@ public class LoadTsFileManager {
               uuid,
               o -> {
                 try {
-                  return new TsFileWriterManager(new File(getNextFolder(), 
uuid));
+                  return getFolderManager()
+                      .getNextWithRetry(folder -> new TsFileWriterManager(new 
File(folder, uuid)));
                 } catch (DiskSpaceInsufficientException e) {
                   exception.set(e);
                   return null;
                 }
               });
+
       if (exception.get() != null || writerManager == null) {
         throw new IOException(
             "Failed to create TsFileWriterManager for uuid "
@@ -255,7 +257,7 @@ public class LoadTsFileManager {
     }
   }
 
-  private String getNextFolder() throws DiskSpaceInsufficientException {
+  private FolderManager getFolderManager() throws 
DiskSpaceInsufficientException {
     if (CONFIG.getLoadTsFileDirs() != LOAD_BASE_DIRS.get()) {
       synchronized (FOLDER_MANAGER) {
         if (CONFIG.getLoadTsFileDirs() != LOAD_BASE_DIRS.get()) {
@@ -263,7 +265,7 @@ public class LoadTsFileManager {
           FOLDER_MANAGER.set(
               new FolderManager(
                   Arrays.asList(LOAD_BASE_DIRS.get()), 
DirectoryStrategyType.SEQUENCE_STRATEGY));
-          return FOLDER_MANAGER.get().getNextFolder();
+          return FOLDER_MANAGER.get();
         }
       }
     }
@@ -274,12 +276,12 @@ public class LoadTsFileManager {
           FOLDER_MANAGER.set(
               new FolderManager(
                   Arrays.asList(LOAD_BASE_DIRS.get()), 
DirectoryStrategyType.SEQUENCE_STRATEGY));
-          return FOLDER_MANAGER.get().getNextFolder();
+          return FOLDER_MANAGER.get();
         }
       }
     }
 
-    return FOLDER_MANAGER.get().getNextFolder();
+    return FOLDER_MANAGER.get();
   }
 
   public boolean loadAll(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/ILoadDiskSelector.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/ILoadDiskSelector.java
index b14f0c4b5df..269228e9fe8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/ILoadDiskSelector.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/ILoadDiskSelector.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.storageengine.load.disk;
 
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
+import org.apache.iotdb.db.exception.load.LoadFileException;
 
 import java.io.File;
 
@@ -32,7 +33,7 @@ public interface ILoadDiskSelector {
       long filePartitionId,
       String tsfileName,
       int tierLevel)
-      throws DiskSpaceInsufficientException;
+      throws DiskSpaceInsufficientException, LoadFileException;
 
   enum LoadDiskSelectorType {
     MIN_IO_FIRST("MIN_IO_FIRST"),
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/InheritSystemMultiDisksStrategySelector.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/InheritSystemMultiDisksStrategySelector.java
index 16e420c5e2f..7739c42a538 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/InheritSystemMultiDisksStrategySelector.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/InheritSystemMultiDisksStrategySelector.java
@@ -20,22 +20,26 @@
 package org.apache.iotdb.db.storageengine.load.disk;
 
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
+import org.apache.iotdb.db.exception.load.LoadFileException;
 import org.apache.iotdb.db.storageengine.rescon.disk.TierManager;
 
 import org.apache.tsfile.fileSystem.FSFactoryProducer;
 import org.apache.tsfile.fileSystem.fsFactory.FSFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 
 public class InheritSystemMultiDisksStrategySelector implements 
ILoadDiskSelector {
 
   protected final FSFactory fsFactory = FSFactoryProducer.getFSFactory();
+  private static final Logger logger =
+      LoggerFactory.getLogger(InheritSystemMultiDisksStrategySelector.class);
 
   public InheritSystemMultiDisksStrategySelector() {
     // empty body
   }
 
-  @Override
   public File getTargetFile(
       File fileToLoad,
       String databaseName,
@@ -43,16 +47,30 @@ public class InheritSystemMultiDisksStrategySelector 
implements ILoadDiskSelecto
       long filePartitionId,
       String tsfileName,
       int tierLevel)
-      throws DiskSpaceInsufficientException {
-    // inherit system multi-disks select strategy, see configuration 
`dn_multi_dir_strategy`
-    return fsFactory.getFile(
-        TierManager.getInstance().getNextFolderForTsFile(tierLevel, false),
-        databaseName
-            + File.separatorChar
-            + dataRegionId
-            + File.separatorChar
-            + filePartitionId
-            + File.separator
-            + tsfileName);
+      throws DiskSpaceInsufficientException, LoadFileException {
+    try {
+      return TierManager.getInstance()
+          .getFolderManager(tierLevel, false)
+          .getNextWithRetry(
+              folder -> {
+                return fsFactory.getFile(
+                    folder,
+                    databaseName
+                        + File.separatorChar
+                        + dataRegionId
+                        + File.separatorChar
+                        + filePartitionId
+                        + File.separator
+                        + tsfileName);
+              });
+    } catch (DiskSpaceInsufficientException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new LoadFileException(
+          String.format(
+              "Storage allocation failed for %s/%s/%s (tier %d)",
+              databaseName, dataRegionId, filePartitionId, tierLevel),
+          e);
+    }
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/MinIOSelector.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/MinIOSelector.java
index f6fac586700..d18be675f25 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/MinIOSelector.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/disk/MinIOSelector.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
+import org.apache.iotdb.db.exception.load.LoadFileException;
 import org.apache.iotdb.metrics.utils.FileStoreUtils;
 
 import org.slf4j.Logger;
@@ -76,7 +77,7 @@ public class MinIOSelector extends 
InheritSystemMultiDisksStrategySelector {
       long filePartitionId,
       String tsfileName,
       int tierLevel)
-      throws DiskSpaceInsufficientException {
+      throws DiskSpaceInsufficientException, LoadFileException {
     File targetFile;
     String fileDirRoot = null;
     try {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
index 0851a698aba..e90292853f1 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
@@ -32,17 +32,35 @@ import 
org.apache.iotdb.db.storageengine.rescon.disk.strategy.SequenceStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class FolderManager {
   private static final Logger logger = 
LoggerFactory.getLogger(FolderManager.class);
 
+  /** Represents the operational states of a data folder. */
+  public enum FolderState {
+    /** Indicates the folder is functioning normally with no issues. */
+    HEALTHY,
+    /** Indicates the folder has operational problems requiring attention. */
+    ABNORMAL
+  }
+
   private final List<String> folders;
+
+  /**
+   * Map storing the state of each folder (HEALTHY/ABNORMAL). Key: folder path 
as String Value:
+   * corresponding FolderState enum value
+   */
+  private final Map<String, FolderState> foldersStates = new HashMap<>();
+
   private final DirectoryStrategy selectStrategy;
 
   public FolderManager(List<String> folders, DirectoryStrategyType type)
       throws DiskSpaceInsufficientException {
     this.folders = folders;
+    folders.forEach(dir -> foldersStates.put(dir, FolderState.HEALTHY));
     switch (type) {
       case SEQUENCE_STRATEGY:
         this.selectStrategy = new SequenceStrategy();
@@ -61,6 +79,7 @@ public class FolderManager {
     }
     try {
       this.selectStrategy.setFolders(folders);
+      this.selectStrategy.setFoldersStates(foldersStates);
     } catch (DiskSpaceInsufficientException e) {
       logger.error("All folders are full, change system mode to read-only.", 
e);
       
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
@@ -69,6 +88,11 @@ public class FolderManager {
     }
   }
 
+  public void updateFolderState(String folder, FolderState state) {
+    foldersStates.replace(folder, state);
+    selectStrategy.updateFolderState(folder, state);
+  }
+
   public String getNextFolder() throws DiskSpaceInsufficientException {
     try {
       return folders.get(selectStrategy.nextFolderIndex());
@@ -80,6 +104,45 @@ public class FolderManager {
     }
   }
 
+  boolean hasHealthyFolder() {
+    return folders.stream()
+        .anyMatch(
+            folder ->
+                foldersStates.getOrDefault(folder, FolderState.ABNORMAL) == 
FolderState.HEALTHY);
+  }
+
+  @FunctionalInterface
+  public interface ThrowingFunction<T, R, E extends Exception> {
+    R apply(T t) throws E;
+  }
+
+  /*
+   * Encapsulates the retry logic for folder operations
+   * @param folderConsumer The operation to perform on the folder (e.g., 
creating TsFileWriterManager)
+   * @return The result of the operation
+   */
+  public <T, E extends Exception> T getNextWithRetry(ThrowingFunction<String, 
T, E> folderConsumer)
+      throws DiskSpaceInsufficientException {
+    String folder = null;
+    while (hasHealthyFolder()) {
+      try {
+        folder = folders.get(selectStrategy.nextFolderIndex());
+      } catch (DiskSpaceInsufficientException e) {
+        logger.error("All folders are full, change system mode to read-only.", 
e);
+        
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
+        
CommonDescriptor.getInstance().getConfig().setStatusReason(NodeStatus.DISK_FULL);
+        throw e;
+      }
+      try {
+        return folderConsumer.apply(folder);
+      } catch (Exception e) {
+        updateFolderState(folder, FolderState.ABNORMAL);
+        logger.warn("Failed to process folder '" + folder);
+      }
+    }
+    throw new DiskSpaceInsufficientException(folders);
+  }
+
   public List<String> getFolders() {
     return folders;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/TierManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/TierManager.java
index b86f36b1c49..d929f765607 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/TierManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/TierManager.java
@@ -190,6 +190,10 @@ public class TierManager {
         : unSeqTiers.get(tierLevel).getNextFolder();
   }
 
+  public FolderManager getFolderManager(int tierLevel, boolean sequence) {
+    return sequence ? seqTiers.get(tierLevel) : unSeqTiers.get(tierLevel);
+  }
+
   public List<String> getAllFilesFolders() {
     List<String> folders = new ArrayList<>(seqDir2TierLevel.keySet());
     folders.addAll(unSeqDir2TierLevel.keySet());
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
index 4cf7764183d..bac8d8e47a8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
@@ -22,12 +22,17 @@ import org.apache.iotdb.commons.cluster.NodeStatus;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
 import org.apache.iotdb.commons.utils.JVMCommonUtils;
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
+import org.apache.iotdb.db.storageengine.rescon.disk.FolderManager;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import static 
org.apache.iotdb.db.storageengine.rescon.disk.FolderManager.FolderState.HEALTHY;
 
 /**
  * The basic class of all the strategies of multiple directories. If a user 
wants to define his own
@@ -63,6 +68,35 @@ public abstract class DirectoryStrategy {
     this.folders = folders;
   }
 
+  /**
+   * Map storing the state of each folder (HEALTHY/ABNORMAL). Key: folder path 
as String Value:
+   * corresponding FolderState enum value
+   */
+  Map<String, FolderManager.FolderState> foldersStates = new HashMap<>();
+
+  /**
+   * Replaces the entire folder states mapping with a new one.
+   *
+   * @param foldersStates new mapping of folder paths to their states
+   */
+  public void setFoldersStates(Map<String, FolderManager.FolderState> 
foldersStates) {
+    this.foldersStates = foldersStates;
+  }
+
+  /**
+   * Updates the state of a specific folder if it exists in the mapping.
+   *
+   * @param folder path of the folder to update
+   * @param state new state to set for the folder
+   */
+  public void updateFolderState(String folder, FolderManager.FolderState 
state) {
+    foldersStates.replace(folder, state);
+  }
+
+  public boolean isUnavailableFolder(String dir) {
+    return (foldersStates.getOrDefault(dir, HEALTHY) != HEALTHY);
+  }
+
   /**
    * Choose a folder to allocate. The user should implement this method to 
define his own strategy.
    *
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MaxDiskUsableSpaceFirstStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MaxDiskUsableSpaceFirstStrategy.java
index e75c0388d6b..dccedaad207 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MaxDiskUsableSpaceFirstStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MaxDiskUsableSpaceFirstStrategy.java
@@ -35,6 +35,9 @@ public class MaxDiskUsableSpaceFirstStrategy extends 
DirectoryStrategy {
 
     for (int i = 0; i < folders.size(); i++) {
       String folder = folders.get(i);
+      if (isUnavailableFolder(folder)) {
+        continue;
+      }
       if (!JVMCommonUtils.hasSpace(folder)) {
         continue;
       }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MinFolderOccupiedSpaceFirstStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MinFolderOccupiedSpaceFirstStrategy.java
index d02083f03c2..70ceb70573e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MinFolderOccupiedSpaceFirstStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/MinFolderOccupiedSpaceFirstStrategy.java
@@ -36,6 +36,9 @@ public class MinFolderOccupiedSpaceFirstStrategy extends 
DirectoryStrategy {
 
     for (int i = 0; i < folders.size(); i++) {
       String folder = folders.get(i);
+      if (isUnavailableFolder(folder)) {
+        continue;
+      }
       if (!JVMCommonUtils.hasSpace(folder)) {
         continue;
       }
@@ -45,6 +48,7 @@ public class MinFolderOccupiedSpaceFirstStrategy extends 
DirectoryStrategy {
         space = JVMCommonUtils.getOccupiedSpace(folder);
       } catch (IOException e) {
         LOGGER.error("Cannot calculate occupied space for path {}.", folder, 
e);
+        continue;
       }
       if (space < minSpace) {
         minSpace = space;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/RandomOnDiskUsableSpaceStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/RandomOnDiskUsableSpaceStrategy.java
index cf4b911c0bb..e564011dc73 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/RandomOnDiskUsableSpaceStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/RandomOnDiskUsableSpaceStrategy.java
@@ -58,6 +58,10 @@ public class RandomOnDiskUsableSpaceStrategy extends 
DirectoryStrategy {
     List<Long> spaceList = new ArrayList<>();
     for (int i = 0; i < folders.size(); i++) {
       String folder = folders.get(i);
+      if (isUnavailableFolder(folder)) {
+        spaceList.add(0L);
+        continue;
+      }
       spaceList.add(JVMCommonUtils.getUsableSpace(folder));
     }
     return spaceList;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/SequenceStrategy.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/SequenceStrategy.java
index ba7265babd5..881623a1882 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/SequenceStrategy.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/SequenceStrategy.java
@@ -60,7 +60,7 @@ public class SequenceStrategy extends DirectoryStrategy {
   private int tryGetNextIndex(int start) throws DiskSpaceInsufficientException 
{
     int index = (start + 1) % folders.size();
     String dir = folders.get(index);
-    while (!JVMCommonUtils.hasSpace(dir)) {
+    while (isUnavailableFolder(dir) || !JVMCommonUtils.hasSpace(dir)) {
       File dirFile = FSFactoryProducer.getFSFactory().getFile(dir);
 
       Long lastPrintTime = dirLastPrintTimeMap.computeIfAbsent(index, i -> 
-1L);
@@ -68,7 +68,7 @@ public class SequenceStrategy extends DirectoryStrategy {
         long freeSpace = dirFile.getFreeSpace();
         long totalSpace = dirFile.getTotalSpace();
         LOGGER.warn(
-            "{} is above the warning threshold, free space {}, total space{}",
+            "{} is above the warning threshold, or not accessible, free space 
{}, total space {}",
             dir,
             freeSpace,
             totalSpace);
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/receiver/IoTDBFileReceiver.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/receiver/IoTDBFileReceiver.java
index 69e5664e127..9d84f4d6e0d 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/receiver/IoTDBFileReceiver.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/receiver/IoTDBFileReceiver.java
@@ -156,48 +156,56 @@ public abstract class IoTDBFileReceiver implements 
IoTDBReceiver {
       }
     }
 
-    final String receiverFileBaseDir;
-    try {
-      receiverFileBaseDir = getReceiverFileBaseDir();
-      if (Objects.isNull(receiverFileBaseDir)) {
+    String receiverFileBaseDir;
+    File newReceiverDir = null;
+    for (int retryTimes = 0; retryTimes <= 1; retryTimes++) {
+      try {
+        receiverFileBaseDir = getReceiverFileBaseDir();
+        if (Objects.isNull(receiverFileBaseDir)) {
+          LOGGER.warn(
+              "Receiver id = {}: Failed to init pipe receiver file folder 
manager because all disks of folders are full.",
+              receiverId.get());
+          return new 
TPipeTransferResp(StatusUtils.getStatus(TSStatusCode.DISK_SPACE_INSUFFICIENT));
+        }
+      } catch (Exception e) {
         LOGGER.warn(
-            "Receiver id = {}: Failed to init pipe receiver file folder 
manager because all disks of folders are full.",
-            receiverId.get());
+            "Receiver id = {}: Failed to create pipe receiver file folder 
because all disks of folders are full.",
+            receiverId.get(),
+            e);
         return new 
TPipeTransferResp(StatusUtils.getStatus(TSStatusCode.DISK_SPACE_INSUFFICIENT));
       }
-    } catch (Exception e) {
-      LOGGER.warn(
-          "Receiver id = {}: Failed to create pipe receiver file folder 
because all disks of folders are full.",
-          receiverId.get(),
-          e);
-      return new 
TPipeTransferResp(StatusUtils.getStatus(TSStatusCode.DISK_SPACE_INSUFFICIENT));
-    }
 
-    // Create a new receiver file dir
-    final File newReceiverDir = new File(receiverFileBaseDir, 
Long.toString(receiverId.get()));
-    if (!newReceiverDir.exists() && !newReceiverDir.mkdirs()) {
+      try {
+        // Create a new receiver file dir
+        newReceiverDir = new File(receiverFileBaseDir, 
Long.toString(receiverId.get()));
+        if (newReceiverDir.exists() || newReceiverDir.mkdirs()) {
+          receiverFileDirWithIdSuffix.set(newReceiverDir);
+          LOGGER.info(
+              "Receiver id = {}: Handshake successfully! Sender's host = {}, 
port = {}. Receiver's file dir = {}.",
+              receiverId.get(),
+              getSenderHost(),
+              getSenderPort(),
+              newReceiverDir.getPath());
+          return new TPipeTransferResp(RpcUtils.SUCCESS_STATUS);
+        }
+      } catch (Exception ignored) {
+      }
       LOGGER.warn(
           "Receiver id = {}: Failed to create receiver file dir {}.",
           receiverId.get(),
           newReceiverDir.getPath());
-      return new TPipeTransferResp(
-          RpcUtils.getStatus(
-              TSStatusCode.PIPE_HANDSHAKE_ERROR,
-              String.format("Failed to create receiver file dir %s.", 
newReceiverDir.getPath())));
+      markFileBaseDirStateAbnormal(receiverFileBaseDir);
     }
-    receiverFileDirWithIdSuffix.set(newReceiverDir);
-
-    LOGGER.info(
-        "Receiver id = {}: Handshake successfully! Sender's host = {}, port = 
{}. Receiver's file dir = {}.",
-        receiverId.get(),
-        getSenderHost(),
-        getSenderPort(),
-        newReceiverDir.getPath());
-    return new TPipeTransferResp(RpcUtils.SUCCESS_STATUS);
+    return new TPipeTransferResp(
+        RpcUtils.getStatus(
+            TSStatusCode.PIPE_HANDSHAKE_ERROR,
+            String.format("Failed to create receiver file dir %s.", 
newReceiverDir.getPath())));
   }
 
   protected abstract String getReceiverFileBaseDir() throws Exception;
 
+  protected abstract void markFileBaseDirStateAbnormal(String dir);
+
   protected abstract String getSenderHost();
 
   protected abstract String getSenderPort();
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/JVMCommonUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/JVMCommonUtils.java
index 2df28b9caae..84f9704e4f0 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/JVMCommonUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/JVMCommonUtils.java
@@ -65,32 +65,44 @@ public class JVMCommonUtils {
    * @return
    */
   public static long getUsableSpace(String dir) {
-    File dirFile = FSFactoryProducer.getFSFactory().getFile(dir);
-    dirFile.mkdirs();
-    return IOUtils.retryNoException(5, 2000L, dirFile::getFreeSpace, space -> 
space > 0).orElse(0L);
+    try {
+      File dirFile = FSFactoryProducer.getFSFactory().getFile(dir);
+      dirFile.mkdirs();
+      return IOUtils.retryNoException(5, 2000L, dirFile::getFreeSpace, space 
-> space > 0)
+          .orElse(0L);
+    } catch (Exception e) {
+      LOGGER.error("Unexpected error checking disk space for directory: {}", 
dir, e);
+      return 0L;
+    }
   }
 
   public static double getDiskFreeRatio(String dir) {
-    File dirFile = FSFactoryProducer.getFSFactory().getFile(dir);
-    if (!dirFile.mkdirs()) {
-      // This may solve getFreeSpace() == 0?
-      dirFile = new File(dir);
-    }
-    long freeSpace =
-        IOUtils.retryNoException(5, 2000L, dirFile::getFreeSpace, space -> 
space > 0).orElse(0L);
-    if (freeSpace == 0) {
-      LOGGER.warn("Cannot get free space for {} after retries, please check 
the disk status", dir);
-    }
-    long totalSpace = dirFile.getTotalSpace();
-    double ratio = 1.0 * freeSpace / totalSpace;
-    if (ratio <= diskSpaceWarningThreshold) {
-      LOGGER.warn(
-          "{} is above the warning threshold, free space {}, total space {}",
-          dir,
-          freeSpace,
-          totalSpace);
+    try {
+      File dirFile = FSFactoryProducer.getFSFactory().getFile(dir);
+      if (!dirFile.mkdirs()) {
+        // This may solve getFreeSpace() == 0?
+        dirFile = new File(dir);
+      }
+      long freeSpace =
+          IOUtils.retryNoException(5, 2000L, dirFile::getFreeSpace, space -> 
space > 0).orElse(0L);
+      if (freeSpace == 0) {
+        LOGGER.warn(
+            "Cannot get free space for {} after retries, please check the disk 
status", dir);
+      }
+      long totalSpace = dirFile.getTotalSpace();
+      double ratio = 1.0 * freeSpace / totalSpace;
+      if (ratio <= diskSpaceWarningThreshold) {
+        LOGGER.warn(
+            "{} is above the warning threshold, free space {}, total space {}",
+            dir,
+            freeSpace,
+            totalSpace);
+      }
+      return ratio;
+    } catch (Exception e) {
+      LOGGER.error("Unexpected error checking disk space for {}", dir, e);
+      return 0;
     }
-    return ratio;
   }
 
   public static boolean hasSpace(String dir) {


Reply via email to