You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by dr...@apache.org on 2022/08/16 13:18:38 UTC

[ratis] 09/12: RATIS-1665. RaftLog avoid converting list (#708)

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

dragonyliu pushed a commit to branch branch-2
in repository https://gitbox.apache.org/repos/asf/ratis.git

commit d80d955204b1f2542a4a7fd75b9c1e720450944b
Author: jiangyuan <ji...@baidu.com>
AuthorDate: Tue Aug 9 13:35:51 2022 +0800

    RATIS-1665. RaftLog avoid converting list (#708)
    
    
    (cherry picked from commit 38a01cdc39b32e69c6c89c8423904842bf7d3cb8)
---
 .../ratis/server/raftlog/RaftLogSequentialOps.java | 13 +++++-
 .../apache/ratis/server/impl/LeaderStateImpl.java  |  2 +-
 .../apache/ratis/server/impl/RaftServerImpl.java   | 48 ++++++++++++----------
 .../org/apache/ratis/server/impl/ServerState.java  |  8 ++--
 .../apache/ratis/server/raftlog/LogProtoUtils.java |  7 +---
 .../apache/ratis/server/raftlog/RaftLogBase.java   |  4 +-
 .../ratis/server/raftlog/memory/MemoryRaftLog.java | 21 +++++-----
 .../server/raftlog/segmented/SegmentedRaftLog.java | 12 +++---
 .../raftlog/segmented/SegmentedRaftLogCache.java   | 15 +++----
 .../server/raftlog/memory/MemoryRaftLogTest.java   | 30 +++++++-------
 .../raftlog/segmented/TestCacheEviction.java       |  6 +--
 .../raftlog/segmented/TestSegmentedRaftLog.java    |  2 +-
 12 files changed, 93 insertions(+), 75 deletions(-)

diff --git a/ratis-server-api/src/main/java/org/apache/ratis/server/raftlog/RaftLogSequentialOps.java b/ratis-server-api/src/main/java/org/apache/ratis/server/raftlog/RaftLogSequentialOps.java
index 34a8f8952..32bd564e0 100644
--- a/ratis-server-api/src/main/java/org/apache/ratis/server/raftlog/RaftLogSequentialOps.java
+++ b/ratis-server-api/src/main/java/org/apache/ratis/server/raftlog/RaftLogSequentialOps.java
@@ -25,6 +25,7 @@ import org.apache.ratis.util.Preconditions;
 import org.apache.ratis.util.StringUtils;
 import org.apache.ratis.util.function.CheckedSupplier;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicReference;
@@ -120,6 +121,16 @@ interface RaftLogSequentialOps {
    */
   CompletableFuture<Long> appendEntry(LogEntryProto entry);
 
+  /**
+   * The same as append(Arrays.asList(entries)).
+   *
+   * @deprecated use {@link #append(List)}
+   */
+  @Deprecated
+  default List<CompletableFuture<Long>> append(LogEntryProto... entries) {
+    return append(Arrays.asList(entries));
+  }
+
   /**
    * Append asynchronously all the given log entries.
    * Used by the followers.
@@ -127,7 +138,7 @@ interface RaftLogSequentialOps {
    * If an existing entry conflicts with a new one (same index but different terms),
    * delete the existing entry and all entries that follow it (ยง5.3).
    */
-  List<CompletableFuture<Long>> append(LogEntryProto... entries);
+  List<CompletableFuture<Long>> append(List<LogEntryProto> entries);
 
   /**
    * Truncate asynchronously the log entries till the given index (inclusively).
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
index 9e170e933..fbcbce448 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
@@ -310,7 +310,7 @@ class LeaderStateImpl implements LeaderState {
         server.getRaftConf(), server.getState().getCurrentTerm(), raftLog.getNextIndex());
     CodeInjectionForTesting.execute(APPEND_PLACEHOLDER,
         server.getId().toString(), null);
-    raftLog.append(placeHolder);
+    raftLog.append(Collections.singletonList(placeHolder));
     processor.start();
     senders.forEach(LogAppender::start);
     return placeHolder;
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
index 6ab0a6a5c..4c798d9d5 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
@@ -1236,9 +1236,9 @@ class RaftServerImpl implements RaftServer.Division,
   }
 
   private void validateEntries(long expectedTerm, TermIndex previous,
-      LogEntryProto... entries) {
-    if (entries != null && entries.length > 0) {
-      final long index0 = entries[0].getIndex();
+      List<LogEntryProto> entries) {
+    if (entries != null && !entries.isEmpty()) {
+      final long index0 = entries.get(0).getIndex();
 
       if (previous == null || previous.getTerm() == 0) {
         Preconditions.assertTrue(index0 == 0,
@@ -1250,13 +1250,14 @@ class RaftServerImpl implements RaftServer.Division,
             previous, 0, index0);
       }
 
-      for (int i = 0; i < entries.length; i++) {
-        final long t = entries[i].getTerm();
+      for (int i = 0; i < entries.size(); i++) {
+        LogEntryProto entry = entries.get(i);
+        final long t = entry.getTerm();
         Preconditions.assertTrue(expectedTerm >= t,
             "Unexpected Term: entries[%s].getTerm()=%s but expectedTerm=%s",
             i, t, expectedTerm);
 
-        final long indexi = entries[i].getIndex();
+        final long indexi = entry.getIndex();
         Preconditions.assertTrue(indexi == index0 + i,
             "Unexpected Index: entries[%s].getIndex()=%s but entries[0].getIndex()=%s",
             i, indexi, index0);
@@ -1277,10 +1278,8 @@ class RaftServerImpl implements RaftServer.Division,
   @Override
   public CompletableFuture<AppendEntriesReplyProto> appendEntriesAsync(AppendEntriesRequestProto r)
       throws IOException {
-    // TODO avoid converting list to array
     final RaftRpcRequestProto request = r.getServerRequest();
-    final LogEntryProto[] entries = r.getEntriesList()
-        .toArray(new LogEntryProto[r.getEntriesCount()]);
+    final List<LogEntryProto> entries = r.getEntriesList();
     final TermIndex previous = r.hasPreviousLog()? TermIndex.valueOf(r.getPreviousLog()) : null;
     final RaftPeerId requestorId = RaftPeerId.valueOf(request.getRequestorId());
 
@@ -1318,7 +1317,7 @@ class RaftServerImpl implements RaftServer.Division,
   }
 
   private void preAppendEntriesAsync(RaftPeerId leaderId, RaftGroupId leaderGroupId, long leaderTerm,
-      TermIndex previous, long leaderCommit, boolean initializing, LogEntryProto... entries) throws IOException {
+      TermIndex previous, long leaderCommit, boolean initializing, List<LogEntryProto> entries) throws IOException {
     CodeInjectionForTesting.execute(APPEND_ENTRIES, getId(),
         leaderId, leaderTerm, previous, leaderCommit, initializing, entries);
 
@@ -1342,8 +1341,8 @@ class RaftServerImpl implements RaftServer.Division,
   @SuppressWarnings("checkstyle:parameternumber")
   private CompletableFuture<AppendEntriesReplyProto> appendEntriesAsync(
       RaftPeerId leaderId, long leaderTerm, TermIndex previous, long leaderCommit, long callId, boolean initializing,
-      List<CommitInfoProto> commitInfos, LogEntryProto... entries) throws IOException {
-    final boolean isHeartbeat = entries.length == 0;
+      List<CommitInfoProto> commitInfos, List<LogEntryProto> entries) throws IOException {
+    final boolean isHeartbeat = entries.isEmpty();
     logAppendEntries(isHeartbeat,
         () -> getMemberId() + ": receive appendEntries(" + leaderId + ", " + leaderTerm + ", "
             + previous + ", " + leaderCommit + ", " + initializing
@@ -1400,7 +1399,7 @@ class RaftServerImpl implements RaftServer.Division,
       state.updateConfiguration(entries);
     }
 
-    final List<CompletableFuture<Long>> futures = entries.length == 0 ? Collections.emptyList()
+    final List<CompletableFuture<Long>> futures = entries.isEmpty() ? Collections.emptyList()
         : state.getLog().append(entries);
     commitInfos.forEach(commitInfoCache::update);
 
@@ -1419,12 +1418,19 @@ class RaftServerImpl implements RaftServer.Division,
     ).thenApply(v -> {
       final AppendEntriesReplyProto reply;
       synchronized(this) {
-        final long commitIndex = ServerImplUtils.effectiveCommitIndex(leaderCommit, previous, entries.length);
+        final long commitIndex = ServerImplUtils.effectiveCommitIndex(leaderCommit, previous, entries.size());
         state.updateCommitIndex(commitIndex, currentTerm, false);
         updateCommitInfoCache();
-        final long n = isHeartbeat? state.getLog().getNextIndex(): entries[entries.length - 1].getIndex() + 1;
-        final long matchIndex = entries.length != 0 ? entries[entries.length - 1].getIndex() :
-            INVALID_LOG_INDEX;
+        final long n;
+        final long matchIndex;
+        if (!isHeartbeat) {
+          LogEntryProto requestLastEntry = entries.get(entries.size() - 1);
+          n = requestLastEntry.getIndex() + 1;
+          matchIndex = requestLastEntry.getIndex();
+        } else {
+          n = state.getLog().getNextIndex();
+          matchIndex = INVALID_LOG_INDEX;
+        }
         reply = ServerProtoUtils.toAppendEntriesReplyProto(leaderId, getMemberId(), currentTerm,
             state.getLog().getLastCommittedIndex(), n, SUCCESS, callId, matchIndex,
             isHeartbeat);
@@ -1437,7 +1443,7 @@ class RaftServerImpl implements RaftServer.Division,
   }
 
   private AppendEntriesReplyProto checkInconsistentAppendEntries(RaftPeerId leaderId, long currentTerm,
-      long followerCommit, TermIndex previous, long callId, boolean isHeartbeat, LogEntryProto... entries) {
+      long followerCommit, TermIndex previous, long callId, boolean isHeartbeat, List<LogEntryProto> entries) {
     final long replyNextIndex = checkInconsistentAppendEntries(previous, entries);
     if (replyNextIndex == -1) {
       return null;
@@ -1450,7 +1456,7 @@ class RaftServerImpl implements RaftServer.Division,
     return reply;
   }
 
-  private long checkInconsistentAppendEntries(TermIndex previous, LogEntryProto... entries) {
+  private long checkInconsistentAppendEntries(TermIndex previous, List<LogEntryProto> entries) {
     // Check if a snapshot installation through state machine is in progress.
     final long installSnapshot = snapshotInstallationHandler.getInProgressInstallSnapshotIndex();
     if (installSnapshot != INVALID_LOG_INDEX) {
@@ -1460,8 +1466,8 @@ class RaftServerImpl implements RaftServer.Division,
 
     // Check that the first log entry is greater than the snapshot index in the latest snapshot and follower's last
     // committed index. If not, reply to the leader the new next index.
-    if (entries != null && entries.length > 0) {
-      final long firstEntryIndex = entries[0].getIndex();
+    if (entries != null && !entries.isEmpty()) {
+      final long firstEntryIndex = entries.get(0).getIndex();
       final long snapshotIndex = state.getSnapshotIndex();
       final long commitIndex =  state.getLog().getLastCommittedIndex();
       final long nextIndex = Math.max(snapshotIndex, commitIndex);
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java
index 52aedfb11..34e9cb92c 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java
@@ -430,10 +430,10 @@ class ServerState implements Closeable {
     LOG.trace("{}: {}", getMemberId(), configurationManager);
   }
 
-  void updateConfiguration(LogEntryProto[] entries) {
-    if (entries != null && entries.length > 0) {
-      configurationManager.removeConfigurations(entries[0].getIndex());
-      Arrays.stream(entries).forEach(this::setRaftConf);
+  void updateConfiguration(List<LogEntryProto> entries) {
+    if (entries != null && !entries.isEmpty()) {
+      configurationManager.removeConfigurations(entries.get(0).getIndex());
+      entries.stream().forEach(this::setRaftConf);
     }
   }
 
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/LogProtoUtils.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/LogProtoUtils.java
index 49caeb9fc..dd8c67dc8 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/LogProtoUtils.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/LogProtoUtils.java
@@ -29,7 +29,6 @@ import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
 import org.apache.ratis.util.Preconditions;
 import org.apache.ratis.util.ProtoUtils;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
@@ -65,11 +64,9 @@ public final class LogProtoUtils {
     return toLogEntryString(entry, null);
   }
 
-  public static String toLogEntriesString(LogEntryProto... entries) {
+  public static String toLogEntriesString(List<LogEntryProto> entries) {
     return entries == null ? null
-        : entries.length == 0 ? "[]"
-        : entries.length == 1 ? toLogEntryString(entries[0])
-        : "" + Arrays.stream(entries).map(LogProtoUtils::toLogEntryString).collect(Collectors.toList());
+        : entries.stream().map(LogProtoUtils::toLogEntryString).collect(Collectors.toList()).toString();
   }
 
   public static String toLogEntriesShortString(List<LogEntryProto> entries) {
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/RaftLogBase.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/RaftLogBase.java
index 60081edd2..11eddb927 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/RaftLogBase.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/RaftLogBase.java
@@ -333,11 +333,11 @@ public abstract class RaftLogBase implements RaftLog {
   protected abstract CompletableFuture<Long> appendEntryImpl(LogEntryProto entry);
 
   @Override
-  public final List<CompletableFuture<Long>> append(LogEntryProto... entries) {
+  public final List<CompletableFuture<Long>> append(List<LogEntryProto> entries) {
     return runner.runSequentially(() -> appendImpl(entries));
   }
 
-  protected abstract List<CompletableFuture<Long>> appendImpl(LogEntryProto... entries);
+  protected abstract List<CompletableFuture<Long>> appendImpl(List<LogEntryProto> entries);
 
   @Override
   public String toString() {
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLog.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLog.java
index 41caef404..0eb7fb159 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLog.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLog.java
@@ -180,9 +180,9 @@ public class MemoryRaftLog extends RaftLogBase {
   }
 
   @Override
-  public List<CompletableFuture<Long>> appendImpl(LogEntryProto... logEntryProtos) {
+  public List<CompletableFuture<Long>> appendImpl(List<LogEntryProto> logEntryProtos) {
     checkLogState();
-    if (logEntryProtos == null || logEntryProtos.length == 0) {
+    if (logEntryProtos == null || logEntryProtos.isEmpty()) {
       return Collections.emptyList();
     }
     try(AutoCloseableLock writeLock = writeLock()) {
@@ -194,26 +194,27 @@ public class MemoryRaftLog extends RaftLogBase {
       // been committed but in the system the entry has not been committed to
       // the quorum of peers' disks.
       boolean toTruncate = false;
-      int truncateIndex = (int) logEntryProtos[0].getIndex();
+      int truncateIndex = (int) logEntryProtos.get(0).getIndex();
       int index = 0;
-      for (; truncateIndex < getNextIndex() && index < logEntryProtos.length;
+      for (; truncateIndex < getNextIndex() && index < logEntryProtos.size();
            index++, truncateIndex++) {
         if (this.entries.get(truncateIndex).getTerm() !=
-            logEntryProtos[index].getTerm()) {
+            logEntryProtos.get(index).getTerm()) {
           toTruncate = true;
           break;
         }
       }
       final List<CompletableFuture<Long>> futures;
       if (toTruncate) {
-        futures = new ArrayList<>(logEntryProtos.length - index + 1);
+        futures = new ArrayList<>(logEntryProtos.size() - index + 1);
         futures.add(truncate(truncateIndex));
       } else {
-        futures = new ArrayList<>(logEntryProtos.length - index);
+        futures = new ArrayList<>(logEntryProtos.size() - index);
       }
-      for (int i = index; i < logEntryProtos.length; i++) {
-        this.entries.add(logEntryProtos[i]);
-        futures.add(CompletableFuture.completedFuture(logEntryProtos[i].getIndex()));
+      for (int i = index; i < logEntryProtos.size(); i++) {
+        LogEntryProto logEntryProto = logEntryProtos.get(i);
+        this.entries.add(logEntryProto);
+        futures.add(CompletableFuture.completedFuture(logEntryProto.getIndex()));
       }
       return futures;
     }
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLog.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLog.java
index e5f4ab87a..74d6a8c03 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLog.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLog.java
@@ -435,9 +435,9 @@ public class SegmentedRaftLog extends RaftLogBase {
   }
 
   @Override
-  public List<CompletableFuture<Long>> appendImpl(LogEntryProto... entries) {
+  public List<CompletableFuture<Long>> appendImpl(List<LogEntryProto> entries) {
     checkLogState();
-    if (entries == null || entries.length == 0) {
+    if (entries == null || entries.isEmpty()) {
       return Collections.emptyList();
     }
     try(AutoCloseableLock writeLock = writeLock()) {
@@ -448,13 +448,13 @@ public class SegmentedRaftLog extends RaftLogBase {
 
       final List<CompletableFuture<Long>> futures;
       if (truncateIndex != -1) {
-        futures = new ArrayList<>(entries.length - index + 1);
+        futures = new ArrayList<>(entries.size() - index + 1);
         futures.add(truncate(truncateIndex));
       } else {
-        futures = new ArrayList<>(entries.length - index);
+        futures = new ArrayList<>(entries.size() - index);
       }
-      for (int i = index; i < entries.length; i++) {
-        futures.add(appendEntry(entries[i]));
+      for (int i = index; i < entries.size(); i++) {
+        futures.add(appendEntry(entries.get(i)));
       }
       return futures;
     }
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java
index 634a2bcb7..7608b30af 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java
@@ -595,25 +595,26 @@ public class SegmentedRaftLogCache {
     }
   }
 
-  TruncateIndices computeTruncateIndices(Consumer<TermIndex> failClientRequest, LogEntryProto... entries) {
+  TruncateIndices computeTruncateIndices(Consumer<TermIndex> failClientRequest, List<LogEntryProto> entries) {
     int arrayIndex = 0;
     long truncateIndex = -1;
 
     try(AutoCloseableLock readLock = closedSegments.readLock()) {
-      final Iterator<TermIndex> i = iterator(entries[0].getIndex());
-      for(; i.hasNext() && arrayIndex < entries.length; arrayIndex++) {
+      final Iterator<TermIndex> i = iterator(entries.get(0).getIndex());
+      for(; i.hasNext() && arrayIndex < entries.size(); arrayIndex++) {
         final TermIndex storedEntry = i.next();
-        Preconditions.assertTrue(storedEntry.getIndex() == entries[arrayIndex].getIndex(),
+        LogEntryProto logEntryProto = entries.get(arrayIndex);
+        Preconditions.assertTrue(storedEntry.getIndex() == logEntryProto.getIndex(),
             "The stored entry's index %s is not consistent with the received entries[%s]'s index %s",
-            storedEntry.getIndex(), arrayIndex, entries[arrayIndex].getIndex());
+            storedEntry.getIndex(), arrayIndex, logEntryProto.getIndex());
 
-        if (storedEntry.getTerm() != entries[arrayIndex].getTerm()) {
+        if (storedEntry.getTerm() != logEntryProto.getTerm()) {
           // we should truncate from the storedEntry's arrayIndex
           truncateIndex = storedEntry.getIndex();
           if (LOG.isTraceEnabled()) {
             LOG.trace("{}: truncate to {}, arrayIndex={}, ti={}, storedEntry={}, entries={}",
                 name, truncateIndex, arrayIndex,
-                TermIndex.valueOf(entries[arrayIndex]), storedEntry,
+                TermIndex.valueOf(logEntryProto), storedEntry,
                 LogProtoUtils.toLogEntriesString(entries));
           }
 
diff --git a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLogTest.java b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLogTest.java
index c2cfb7580..086c10dea 100644
--- a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLogTest.java
+++ b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/memory/MemoryRaftLogTest.java
@@ -19,6 +19,8 @@ package org.apache.ratis.server.raftlog.memory;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import org.apache.log4j.Level;
 import org.apache.ratis.BaseTest;
@@ -52,20 +54,20 @@ public class MemoryRaftLogTest extends BaseTest {
 
     MemoryRaftLog raftLog = new MemoryRaftLog(memberId, () -> -1, prop);
     raftLog.open(RaftLog.INVALID_LOG_INDEX, null);
-    LogEntryProto[] entries1 = new LogEntryProto[2];
-    entries1[0] = LogEntryProto.newBuilder().setIndex(0).setTerm(0).build();
-    entries1[1] = LogEntryProto.newBuilder().setIndex(1).setTerm(0).build();
+    List<LogEntryProto> entries1 = new ArrayList<>();
+    entries1.add(LogEntryProto.newBuilder().setIndex(0).setTerm(0).build());
+    entries1.add(LogEntryProto.newBuilder().setIndex(1).setTerm(0).build());
     raftLog.append(entries1).forEach(CompletableFuture::join);
 
-    LogEntryProto[] entries2 = new LogEntryProto[1];
-    entries2[0] = LogEntryProto.newBuilder().setIndex(0).setTerm(0).build();
+    List<LogEntryProto> entries2 = new ArrayList<>();
+    entries2.add(LogEntryProto.newBuilder().setIndex(0).setTerm(0).build());
     raftLog.append(entries2).forEach(CompletableFuture::join);
 
     final LogEntryHeader[] termIndices = raftLog.getEntries(0, 10);
     assertEquals(2, termIndices.length);
     for (int i = 0; i < 2; i++) {
-      assertEquals(entries1[i].getIndex(), termIndices[i].getIndex());
-      assertEquals(entries1[i].getTerm(), termIndices[i].getTerm());
+      assertEquals(entries1.get(i).getIndex(), termIndices[i].getIndex());
+      assertEquals(entries1.get(i).getTerm(), termIndices[i].getTerm());
     }
   }
 
@@ -80,18 +82,18 @@ public class MemoryRaftLogTest extends BaseTest {
 
     MemoryRaftLog raftLog = new MemoryRaftLog(memberId, () -> -1, prop);
     raftLog.open(RaftLog.INVALID_LOG_INDEX, null);
-    LogEntryProto[] entries1 = new LogEntryProto[2];
-    entries1[0] = LogEntryProto.newBuilder().setIndex(0).setTerm(0).build();
-    entries1[1] = LogEntryProto.newBuilder().setIndex(1).setTerm(0).build();
+    List<LogEntryProto> entries1 = new ArrayList<>();
+    entries1.add(LogEntryProto.newBuilder().setIndex(0).setTerm(0).build());
+    entries1.add(LogEntryProto.newBuilder().setIndex(1).setTerm(0).build());
     raftLog.append(entries1).forEach(CompletableFuture::join);
 
-    LogEntryProto[] entries2 = new LogEntryProto[1];
-    entries2[0] = LogEntryProto.newBuilder().setIndex(0).setTerm(2).build();
+    List<LogEntryProto> entries2 = new ArrayList<>();
+    entries2.add(LogEntryProto.newBuilder().setIndex(0).setTerm(2).build());
     raftLog.append(entries2).forEach(CompletableFuture::join);
 
     final LogEntryHeader[] termIndices = raftLog.getEntries(0, 10);
     assertEquals(1, termIndices.length);
-    assertEquals(entries2[0].getIndex(), termIndices[0].getIndex());
-    assertEquals(entries2[0].getTerm(), termIndices[0].getTerm());
+    assertEquals(entries2.get(0).getIndex(), termIndices[0].getIndex());
+    assertEquals(entries2.get(0).getTerm(), termIndices[0].getTerm());
   }
 }
diff --git a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestCacheEviction.java b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestCacheEviction.java
index a1e18a86d..87dd2ef37 100644
--- a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestCacheEviction.java
+++ b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestCacheEviction.java
@@ -171,7 +171,7 @@ public class TestCacheEviction extends BaseTest {
     final SegmentedRaftLog raftLog = RaftServerTestUtil.newSegmentedRaftLog(memberId, info, storage, prop);
     raftLog.open(RaftLog.INVALID_LOG_INDEX, null);
     List<SegmentRange> slist = TestSegmentedRaftLog.prepareRanges(0, maxCachedNum, 7, 0);
-    LogEntryProto[] entries = generateEntries(slist);
+    List<LogEntryProto> entries = generateEntries(slist);
     raftLog.append(entries).forEach(CompletableFuture::join);
 
     // check the current cached segment number: the last segment is still open
@@ -190,7 +190,7 @@ public class TestCacheEviction extends BaseTest {
         raftLog.getRaftLogCache().getCachedSegmentNum());
   }
 
-  private LogEntryProto[] generateEntries(List<SegmentRange> slist) {
+  private List<LogEntryProto> generateEntries(List<SegmentRange> slist) {
     List<LogEntryProto> eList = new ArrayList<>();
     for (SegmentRange range : slist) {
       for (long index = range.start; index <= range.end; index++) {
@@ -198,6 +198,6 @@ public class TestCacheEviction extends BaseTest {
         eList.add(LogProtoUtils.toLogEntryProto(m.getLogEntryContent(), range.term, index));
       }
     }
-    return eList.toArray(new LogEntryProto[eList.size()]);
+    return eList;
   }
 }
diff --git a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestSegmentedRaftLog.java b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestSegmentedRaftLog.java
index b4bb098a8..a78c102ba 100644
--- a/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestSegmentedRaftLog.java
+++ b/ratis-test/src/test/java/org/apache/ratis/server/raftlog/segmented/TestSegmentedRaftLog.java
@@ -523,7 +523,7 @@ public class TestSegmentedRaftLog extends BaseTest {
       LOG.info("newEntries[0] = {}", newEntries.get(0));
       final int last = newEntries.size() - 1;
       LOG.info("newEntries[{}] = {}", last, newEntries.get(last));
-      raftLog.append(newEntries.toArray(new LogEntryProto[0])).forEach(CompletableFuture::join);
+      raftLog.append(newEntries).forEach(CompletableFuture::join);
 
       checkFailedEntries(entries, 650, retryCache);
       checkEntries(raftLog, entries, 0, 650);