public static WALMetaData readFromWALFile(File logFile, FileChannel channel) throws IOException {
    if (channel.size() < WALFileVersion.V2.getVersionBytes().length
        || !isValidMagicString(channel)) {
      throw new BrokenWALFileException(logFile);
    }

    // load metadata size
    WALMetaData metaData = null;
    long position;
    try {
      ByteBuffer metadataSizeBuf = ByteBuffer.allocate(Integer.BYTES);
      WALFileVersion version = WALFileVersion.getVersion(channel);
      position = channel.size() - Integer.BYTES - (version.getVersionBytes().length);
      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 BrokenWALFileException(logFile);
    } catch (IOException e) {
      throw e;
    } catch (Exception e) {
      throw new IOException("Unexpected exception", e);
    }
    return metaData;
  }
Metadata exists at the end of each wal file, including each entry's size, search index of first
entry and the number of entries.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/io/WALMetaData.java