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

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

commit 35e36d58f587a2b8fa77b681804ee6891a51812b
Author: shuwenwei <[email protected]>
AuthorDate: Tue Jun 9 16:01:39 2026 +0800

    Fix empty snapshot loading and region cleanup
    
    Allow loading snapshots that do not contain seq or unseq data directories 
so empty regions can be migrated successfully.
    
    Skip table disk usage index removal for tree-model regions and complete 
remove operations when no writer exists to avoid delete-region timeouts.
---
 .../db/storageengine/dataregion/DataRegion.java    |  4 ++-
 .../dataregion/snapshot/SnapshotLoader.java        | 10 ++++---
 .../tableDiskUsageIndex/TableDiskUsageIndex.java   | 31 +++++++++++++---------
 .../dataregion/snapshot/IoTDBSnapshotTest.java     | 26 ++++++++++++++++++
 4 files changed, 54 insertions(+), 17 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
index 7289e83cc9f..0860e7539a1 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
@@ -2201,7 +2201,9 @@ public class DataRegion implements IDataRegionForQuery {
         databaseName + "-" + dataRegionIdString,
         systemDir);
     int regionId = dataRegionId.getId();
-    TableDiskUsageIndex.getInstance().remove(databaseName, regionId);
+    if (isTableModel) {
+      TableDiskUsageIndex.getInstance().remove(databaseName, regionId);
+    }
     
FileTimeIndexCacheRecorder.getInstance().removeFileTimeIndexCache(regionId);
     writeLock("deleteFolder");
     try {
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 c32f2301289..ba89bfc6c54 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
@@ -250,6 +250,10 @@ public class SnapshotLoader {
 
   private void createLinksFromSnapshotDirToDataDirWithoutLog(File sourceDir)
       throws IOException, DiskSpaceInsufficientException {
+    if (!sourceDir.exists()) {
+      throw new IOException(
+          String.format("Cannot find snapshot directory %s", 
sourceDir.getAbsolutePath()));
+    }
     File seqFileDir =
         new File(
             sourceDir,
@@ -267,10 +271,8 @@ public class SnapshotLoader {
                 + File.separator
                 + dataRegionId);
     if (!seqFileDir.exists() && !unseqFileDir.exists()) {
-      throw new IOException(
-          String.format(
-              "Cannot find %s or %s",
-              seqFileDir.getAbsolutePath(), unseqFileDir.getAbsolutePath()));
+      LOGGER.warn("No seq or unseq files in snapshot {}, skip creating file 
links", sourceDir);
+      return;
     }
     FolderManager folderManager =
         new FolderManager(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/utils/tableDiskUsageIndex/TableDiskUsageIndex.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/utils/tableDiskUsageIndex/TableDiskUsageIndex.java
index 40e04fc2678..543356c98bc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/utils/tableDiskUsageIndex/TableDiskUsageIndex.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/utils/tableDiskUsageIndex/TableDiskUsageIndex.java
@@ -443,18 +443,25 @@ public class TableDiskUsageIndex {
 
     @Override
     public void apply(TableDiskUsageIndex tableDiskUsageIndex) {
-      tableDiskUsageIndex.writerMap.computeIfPresent(
-          regionId,
-          (k, writer) -> {
-            if (writer.getActiveReaderNum() > 0) {
-              // If there are active readers, defer removal until all readers 
finish
-              writer.setRemovedFuture(future);
-              return writer;
-            }
-            writer.close();
-            future.complete(null);
-            return null;
-          });
+      DataRegionTableSizeIndexWriter removedWriter = null;
+      try {
+        removedWriter =
+            tableDiskUsageIndex.writerMap.computeIfPresent(
+                regionId,
+                (k, writer) -> {
+                  if (writer.getActiveReaderNum() > 0) {
+                    // If there are active readers, defer removal until all 
readers finish
+                    writer.setRemovedFuture(future);
+                    return writer;
+                  }
+                  writer.close();
+                  return null;
+                });
+      } finally {
+        if (removedWriter == null) {
+          future.complete(null);
+        }
+      }
     }
   }
 
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/IoTDBSnapshotTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/IoTDBSnapshotTest.java
index f2ec78777cd..29fe4f13586 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/IoTDBSnapshotTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/IoTDBSnapshotTest.java
@@ -183,6 +183,32 @@ public class IoTDBSnapshotTest {
     }
   }
 
+  @Test
+  public void testLoadEmptySnapshotWithoutLog() throws IOException {
+    String[][] originDataDirs = 
IoTDBDescriptor.getInstance().getConfig().getTierDataDirs();
+    IoTDBDescriptor.getInstance().getConfig().setTierDataDirs(testDataDirs);
+    TierManager.getInstance().resetFolders();
+    File snapshotDir = new File("target" + File.separator + "empty-snapshot");
+    try {
+      if (snapshotDir.exists()) {
+        FileUtils.recursivelyDeleteFolder(snapshotDir.getAbsolutePath());
+      }
+      Assert.assertTrue(snapshotDir.mkdirs());
+
+      DataRegion dataRegion =
+          new SnapshotLoader(snapshotDir.getAbsolutePath(), testSgName, "0")
+              .loadSnapshotForStateMachine();
+
+      Assert.assertNotNull(dataRegion);
+      assertEquals(0, 
dataRegion.getTsFileManager().getTsFileList(true).size());
+      assertEquals(0, 
dataRegion.getTsFileManager().getTsFileList(false).size());
+    } finally {
+      FileUtils.recursivelyDeleteFolder(snapshotDir.getAbsolutePath());
+      
IoTDBDescriptor.getInstance().getConfig().setTierDataDirs(originDataDirs);
+      TierManager.getInstance().resetFolders();
+    }
+  }
+
   @Test
   public void testLoadSnapshot()
       throws IOException, WriteProcessException, DataRegionException, 
DirectoryNotLegalException {

Reply via email to