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

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 99a833c29 Ratis-2031. Add peer info to response of GroupInfoCommand 
CLI (#1047)
99a833c29 is described below

commit 99a833c29eb28203cc6107ede26318ff86e636e1
Author: DaveTeng0 <[email protected]>
AuthorDate: Thu Mar 7 16:37:16 2024 -0800

    Ratis-2031. Add peer info to response of GroupInfoCommand CLI (#1047)
---
 .../apache/ratis/client/impl/ClientProtoUtils.java |  4 +-
 .../org/apache/ratis/protocol/GroupInfoReply.java  | 13 ++++--
 ratis-proto/src/main/proto/Raft.proto              | 10 +++++
 .../apache/ratis/server/impl/RaftServerImpl.java   | 16 ++++++-
 .../ratis/shell/cli/sh/group/GroupInfoCommand.java |  1 +
 .../shell/cli/sh/GroupCommandIntegrationTest.java  | 49 ++++++++++++++++++++++
 6 files changed, 88 insertions(+), 5 deletions(-)

diff --git 
a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java 
b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
index db1983195..003f202bd 100644
--- 
a/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
+++ 
b/ratis-client/src/main/java/org/apache/ratis/client/impl/ClientProtoUtils.java
@@ -364,6 +364,7 @@ public interface ClientProtoUtils {
         b.setIsRaftStorageHealthy(reply.isRaftStorageHealthy());
         b.setRole(reply.getRoleInfoProto());
         b.addAllCommitInfos(reply.getCommitInfos());
+        b.setLogInfo(reply.getLogInfoProto());
       }
     }
     return b.build();
@@ -506,7 +507,8 @@ public interface ClientProtoUtils {
         ProtoUtils.toRaftGroup(replyProto.getGroup()),
         replyProto.getRole(),
         replyProto.getIsRaftStorageHealthy(),
-        replyProto.hasConf()? replyProto.getConf(): null);
+        replyProto.hasConf()? replyProto.getConf(): null,
+        replyProto.getLogInfo());
   }
 
   static Message toMessage(final ClientMessageEntryProto p) {
diff --git 
a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java 
b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java
index 632fa6529..bfac81a2b 100644
--- a/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java
+++ b/ratis-common/src/main/java/org/apache/ratis/protocol/GroupInfoReply.java
@@ -19,6 +19,7 @@ package org.apache.ratis.protocol;
 
 import org.apache.ratis.proto.RaftProtos.RaftConfigurationProto;
 import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
+import org.apache.ratis.proto.RaftProtos.LogInfoProto;
 import org.apache.ratis.proto.RaftProtos.RoleInfoProto;
 
 import java.util.Collection;
@@ -33,25 +34,27 @@ public class GroupInfoReply extends RaftClientReply {
   private final RoleInfoProto roleInfoProto;
   private final boolean isRaftStorageHealthy;
   private final RaftConfigurationProto conf;
+  private final LogInfoProto logInfoProto;
 
   public GroupInfoReply(RaftClientRequest request, Collection<CommitInfoProto> 
commitInfos,
       RaftGroup group, RoleInfoProto roleInfoProto, boolean 
isRaftStorageHealthy,
-      RaftConfigurationProto conf) {
+      RaftConfigurationProto conf, LogInfoProto logInfoProto) {
     this(request.getClientId(), request.getServerId(), 
request.getRaftGroupId(),
         request.getCallId(), commitInfos,
-        group, roleInfoProto, isRaftStorageHealthy, conf);
+        group, roleInfoProto, isRaftStorageHealthy, conf, logInfoProto);
   }
 
   @SuppressWarnings("parameternumber")
   public GroupInfoReply(ClientId clientId, RaftPeerId serverId, RaftGroupId 
groupId, long callId,
       Collection<CommitInfoProto> commitInfos,
       RaftGroup group, RoleInfoProto roleInfoProto, boolean 
isRaftStorageHealthy,
-      RaftConfigurationProto conf) {
+      RaftConfigurationProto conf, LogInfoProto logInfoProto) {
     super(clientId, serverId, groupId, callId, true, null, null, 0L, 
commitInfos);
     this.group = group;
     this.roleInfoProto = roleInfoProto;
     this.isRaftStorageHealthy = isRaftStorageHealthy;
     this.conf = conf;
+    this.logInfoProto = logInfoProto;
   }
 
   public RaftGroup getGroup() {
@@ -69,4 +72,8 @@ public class GroupInfoReply extends RaftClientReply {
   public Optional<RaftConfigurationProto> getConf() {
     return Optional.ofNullable(conf);
   }
+
+  public LogInfoProto getLogInfoProto() {
+    return logInfoProto;
+  }
 }
diff --git a/ratis-proto/src/main/proto/Raft.proto 
b/ratis-proto/src/main/proto/Raft.proto
index 586ec1b05..edc57ec65 100644
--- a/ratis-proto/src/main/proto/Raft.proto
+++ b/ratis-proto/src/main/proto/Raft.proto
@@ -556,4 +556,14 @@ message GroupInfoReplyProto {
   bool isRaftStorageHealthy = 4;
   repeated CommitInfoProto commitInfos = 5;
   RaftConfigurationProto conf = 6;
+  LogInfoProto logInfo = 7;
+}
+
+/** Add new LogInfoProto for RATIS-2030, allow GroupInfoCommand to show each 
server's last committed log,
+    last applied log, last snapshot log, last entry log.*/
+message LogInfoProto {
+  TermIndexProto lastSnapshot = 1;
+  TermIndexProto applied = 2;
+  TermIndexProto committed = 3;
+  TermIndexProto lastEntry = 4;
 }
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 0885fb807..17a741e70 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
@@ -24,6 +24,7 @@ import 
org.apache.ratis.proto.RaftProtos.AppendEntriesReplyProto;
 import org.apache.ratis.proto.RaftProtos.AppendEntriesReplyProto.AppendResult;
 import org.apache.ratis.proto.RaftProtos.AppendEntriesRequestProto;
 import org.apache.ratis.proto.RaftProtos.CommitInfoProto;
+import org.apache.ratis.proto.RaftProtos.LogInfoProto;
 import org.apache.ratis.proto.RaftProtos.InstallSnapshotReplyProto;
 import org.apache.ratis.proto.RaftProtos.InstallSnapshotRequestProto;
 import org.apache.ratis.proto.RaftProtos.InstallSnapshotResult;
@@ -642,7 +643,20 @@ class RaftServerImpl implements RaftServer.Division,
     final RaftConfigurationProto conf =
         LogProtoUtils.toRaftConfigurationProtoBuilder(getRaftConf()).build();
     return new GroupInfoReply(request, getCommitInfos(), getGroup(), 
getRoleInfoProto(),
-        dir.isHealthy(), conf);
+        dir.isHealthy(), conf, getLogInfo());
+  }
+
+  LogInfoProto getLogInfo(){
+    final RaftLog log = getRaftLog();
+    LogInfoProto.Builder logInfoBuilder = LogInfoProto.newBuilder()
+        .setApplied(getStateMachine().getLastAppliedTermIndex().toProto())
+        .setCommitted(log.getTermIndex(log.getLastCommittedIndex()).toProto())
+        .setLastEntry(log.getLastEntryTermIndex().toProto());
+    final SnapshotInfo snapshot = getStateMachine().getLatestSnapshot();
+    if (snapshot != null) {
+      logInfoBuilder.setLastSnapshot(snapshot.getTermIndex().toProto());
+    }
+    return logInfoBuilder.build();
   }
 
   RoleInfoProto getRoleInfoProto() {
diff --git 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupInfoCommand.java
 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupInfoCommand.java
index d2c4e6599..0125440e9 100644
--- 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupInfoCommand.java
+++ 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupInfoCommand.java
@@ -54,6 +54,7 @@ public class GroupInfoCommand extends AbstractRatisCommand {
       printf("leader info: %s(%s)%n%n", leader.getId().toStringUtf8(), 
leader.getAddress());
     }
     println(reply.getCommitInfos());
+    println(reply.getLogInfoProto());
     return 0;
   }
 
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
index 83c05bfdd..6900d4804 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
@@ -20,6 +20,7 @@ package org.apache.ratis.shell.cli.sh;
 import org.apache.ratis.RaftTestUtil;
 import org.apache.ratis.client.RaftClient;
 import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.protocol.RaftClientReply;
 import org.apache.ratis.server.RaftServer;
 import org.apache.ratis.server.RaftServerConfigKeys;
 import org.apache.ratis.server.impl.MiniRaftCluster;
@@ -90,4 +91,52 @@ public abstract class GroupCommandIntegrationTest<CLUSTER 
extends MiniRaftCluste
     String info = result.substring(0, hearder.length());
     Assertions.assertEquals(hearder, info);
   }
+
+  @Test
+  public void testGroupInfoCommandIncludesCorrectLogInfo() throws Exception {
+    // set number of server to 1 so that we can make sure which server returns 
the LogInfoProto
+    // since information of applied index, snapshot index, and last entry 
index are not shared between servers
+    runWithNewCluster(1, this::runTestGroupInfoCommandWithLogInfoVerification);
+  }
+
+  void runTestGroupInfoCommandWithLogInfoVerification(MiniRaftCluster cluster) 
throws Exception {
+    RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+
+    try (final RaftClient client = cluster.createClient(leader.getId())) {
+      for (int i = 0; i < 
RaftServerConfigKeys.Snapshot.creationGap(getProperties()); i++) {
+        RaftClientReply
+            reply = client.io().send(new RaftTestUtil.SimpleMessage("m" + i));
+        Assertions.assertTrue(reply.isSuccess());
+      }
+    }
+
+    leader.getStateMachine().takeSnapshot();
+
+    final String address = getClusterAddress(cluster);
+    final StringPrintStream out = new StringPrintStream();
+    RatisShell shell = new RatisShell(out.getPrintStream());
+    int ret = shell.run("group", "info", "-peers", address);
+    Assertions.assertEquals(0 , ret);
+    String result = out.toString().trim();
+    String hearder = String.format("group id: %s%sleader info: %s(%s)%s%s",
+        cluster.getGroupId().getUuid(), NEW_LINE, leader.getId(),
+        cluster.getLeader().getPeer().getAddress(), NEW_LINE, NEW_LINE);
+    String info = result.substring(0, hearder.length());
+    Assertions.assertEquals(hearder, info);
+    long currentTerm = leader.getInfo().getCurrentTerm();
+    String LogInfoProtoFormat = "%s {" + NEW_LINE + "  term: " + currentTerm + 
NEW_LINE + "  index: %s";
+    Assertions.assertTrue(result.contains(
+        String.format(LogInfoProtoFormat, "applied",
+            leader.getStateMachine().getLastAppliedTermIndex().getIndex())));
+    Assertions.assertTrue(result.contains(
+        String.format(LogInfoProtoFormat, "committed",
+            leader.getRaftLog().getLastCommittedIndex())));
+    Assertions.assertTrue(result.contains(
+        String.format(LogInfoProtoFormat, "lastSnapshot",
+            leader.getStateMachine().getLatestSnapshot().getIndex())));
+    Assertions.assertTrue(result.contains(
+        String.format(LogInfoProtoFormat, "lastEntry",
+            leader.getRaftLog().getLastCommittedIndex())));
+  }
+
 }

Reply via email to