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 de3adcd0363 Fix uncaught IllegalArgumentException when reading broken 
WAL files (#12912)
de3adcd0363 is described below

commit de3adcd03633f9e049e4a3e3ed4710fcda4ec83e
Author: Jiang Tian <[email protected]>
AuthorDate: Tue Jul 16 09:35:36 2024 +0800

    Fix uncaught IllegalArgumentException when reading broken WAL files (#12912)
    
    * Fix uncaught IllegalArgumentException when reading broken WAL files
    
    * spotless
    
    * also catch other exception
---
 .../dataregion/wal/io/WALMetaData.java             | 65 +++++++++++++---------
 .../dataregion/wal/io/WALFileTest.java             | 15 +++++
 2 files changed, 53 insertions(+), 27 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALMetaData.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALMetaData.java
index ecd44268f59..b5c71ba0e5c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALMetaData.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALMetaData.java
@@ -131,38 +131,49 @@ public class WALMetaData implements SerializedSize {
 
   public static WALMetaData readFromWALFile(File logFile, FileChannel channel) 
throws IOException {
     if (channel.size() < WALWriter.MAGIC_STRING_V2_BYTES || 
!isValidMagicString(channel)) {
-      throw new IOException(String.format("Broken wal file %s", logFile));
+      throw new IOException(
+          String.format("Broken wal file %s, size %d", logFile, 
logFile.length()));
     }
 
     // load metadata size
-    ByteBuffer metadataSizeBuf = ByteBuffer.allocate(Integer.BYTES);
+    WALMetaData metaData = null;
     long position;
-    WALFileVersion version = WALFileVersion.getVersion(channel);
-    position =
-        channel.size()
-            - Integer.BYTES
-            - (version == WALFileVersion.V2
-                ? WALWriter.MAGIC_STRING_V2_BYTES
-                : WALWriter.MAGIC_STRING_V1_BYTES);
-    channel.read(metadataSizeBuf, position);
-    metadataSizeBuf.flip();
-    // load metadata
-    int metadataSize = metadataSizeBuf.getInt();
-    ByteBuffer metadataBuf = ByteBuffer.allocate(metadataSize);
-    channel.read(metadataBuf, position - metadataSize);
-    metadataBuf.flip();
-    WALMetaData metaData = WALMetaData.deserialize(metadataBuf);
-    // versions before V1.3, should recover memTable ids from entries
-    if (metaData.memTablesId.isEmpty()) {
-      int offset = Byte.BYTES;
-      for (int size : metaData.buffersSize) {
-        channel.position(offset);
-        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
-        channel.read(buffer);
-        buffer.clear();
-        metaData.memTablesId.add(buffer.getLong());
-        offset += size;
+    try {
+      ByteBuffer metadataSizeBuf = ByteBuffer.allocate(Integer.BYTES);
+      WALFileVersion version = WALFileVersion.getVersion(channel);
+      position =
+          channel.size()
+              - Integer.BYTES
+              - (version == WALFileVersion.V2
+                  ? WALWriter.MAGIC_STRING_V2_BYTES
+                  : WALWriter.MAGIC_STRING_V1_BYTES);
+      channel.read(metadataSizeBuf, position);
+      metadataSizeBuf.flip();
+      // load metadata
+      int metadataSize = metadataSizeBuf.getInt();
+      ByteBuffer metadataBuf = ByteBuffer.allocate(metadataSize);
+      channel.read(metadataBuf, position - metadataSize);
+      metadataBuf.flip();
+      metaData = WALMetaData.deserialize(metadataBuf);
+      // versions before V1.3, should recover memTable ids from entries
+      if (metaData.memTablesId.isEmpty()) {
+        int offset = Byte.BYTES;
+        for (int size : metaData.buffersSize) {
+          channel.position(offset);
+          ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+          channel.read(buffer);
+          buffer.clear();
+          metaData.memTablesId.add(buffer.getLong());
+          offset += size;
+        }
       }
+    } catch (IllegalArgumentException e) {
+      throw new IOException(
+          String.format("Broken wal file %s, size %d", logFile, 
logFile.length()));
+    } catch (IOException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new IOException("Unexpected exception", e);
     }
     return metaData;
   }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALFileTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALFileTest.java
index 603231ccbdd..d1c0a86ce39 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALFileTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALFileTest.java
@@ -45,12 +45,15 @@ import org.junit.Test;
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 
 public class WALFileTest {
 
@@ -154,6 +157,18 @@ public class WALFileTest {
     assertEquals(expectedWALEntries, actualWALEntries);
   }
 
+  @Test
+  public void testReadMetadataFromBrokenFile() throws IOException {
+    ILogWriter walWriter = new WALWriter(walFile);
+    assertThrows(
+        IOException.class,
+        () -> WALMetaData.readFromWALFile(walFile, 
FileChannel.open(walFile.toPath())));
+    walWriter.close();
+    WALMetaData walMetaData =
+        WALMetaData.readFromWALFile(walFile, 
FileChannel.open(walFile.toPath()));
+    assertTrue(walMetaData.getMemTablesId().isEmpty());
+  }
+
   public static InsertRowNode getInsertRowNode(String devicePath) throws 
IllegalPathException {
     long time = 110L;
     TSDataType[] dataTypes =

Reply via email to