You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2026/06/22 15:47:00 UTC

(hbase) branch branch-3 updated: HBASE-30249 Make TestSyncReplicationStandbyKillMaster stable (#8393)

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

Apache9 pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 055b7d970c3 HBASE-30249 Make TestSyncReplicationStandbyKillMaster stable (#8393)
055b7d970c3 is described below

commit 055b7d970c37bf4a8c53f2a96d32db8ce34eab89
Author: Duo Zhang <zh...@apache.org>
AuthorDate: Mon Jun 22 23:43:20 2026 +0800

    HBASE-30249 Make TestSyncReplicationStandbyKillMaster stable (#8393)
    
    Signed-off-by: Xiao Liu <li...@apache.org>
    (cherry picked from commit c726596ae6d8ce0abe09f92a0cd631725c5d58a8)
---
 .../TestSyncReplicationStandbyKillMaster.java      | 69 +++++++++++++++-------
 1 file changed, 49 insertions(+), 20 deletions(-)

diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestSyncReplicationStandbyKillMaster.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestSyncReplicationStandbyKillMaster.java
index e2a337504c0..5074279b7be 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestSyncReplicationStandbyKillMaster.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestSyncReplicationStandbyKillMaster.java
@@ -17,13 +17,24 @@
  */
 package org.apache.hadoop.hbase.replication;
 
+import static org.apache.hadoop.hbase.coprocessor.CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.io.IOException;
+import java.time.Duration;
+import java.util.Optional;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
+import org.apache.hadoop.hbase.coprocessor.MasterObserver;
+import org.apache.hadoop.hbase.coprocessor.ObserverContext;
 import org.apache.hadoop.hbase.master.MasterFileSystem;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
 import org.apache.hadoop.hbase.testclassification.ReplicationTests;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
@@ -31,14 +42,38 @@ import org.slf4j.LoggerFactory;
 
 @Tag(ReplicationTests.TAG)
 @Tag(LargeTests.TAG)
-public class TestSyncReplicationStandbyKillMaster extends SyncReplicationTestBase {
+public class TestSyncReplicationStandbyKillMaster extends SyncReplicationTestBaseNoBeforeAll {
 
   private static final Logger LOG =
     LoggerFactory.getLogger(TestSyncReplicationStandbyKillMaster.class);
 
-  private final long SLEEP_TIME = 2000;
+  private static final int COUNT = 1000;
 
-  private final int COUNT = 1000;
+  private static volatile boolean KILL_MASTER = false;
+
+  public static final class TransitCP implements MasterCoprocessor, MasterObserver {
+
+    @Override
+    public void preTransitReplicationPeerSyncReplicationState(
+      ObserverContext<MasterCoprocessorEnvironment> ctx, String peerId, SyncReplicationState state)
+      throws IOException {
+      if (KILL_MASTER) {
+        KILL_MASTER = false;
+        UTIL2.getMiniHBaseCluster().getMaster().abort("Stop master for test");
+      }
+    }
+
+    @Override
+    public Optional<MasterObserver> getMasterObserver() {
+      return Optional.of(this);
+    }
+  }
+
+  @BeforeAll
+  public static void setUp() throws Exception {
+    UTIL2.getConfiguration().set(MASTER_COPROCESSOR_CONF_KEY, TransitCP.class.getName());
+    startClusters();
+  }
 
   @Test
   public void testStandbyKillMaster() throws Exception {
@@ -56,30 +91,24 @@ public class TestSyncReplicationStandbyKillMaster extends SyncReplicationTestBas
     write(UTIL1, 0, COUNT);
     UTIL1.shutdownMiniCluster();
 
-    Thread t = new Thread(() -> {
-      try {
-        Thread.sleep(SLEEP_TIME);
-        UTIL2.getMiniHBaseCluster().getMaster().stop("Stop master for test");
-      } catch (Exception e) {
-        LOG.error("Failed to stop master", e);
-      }
-    });
-    t.start();
-
+    KILL_MASTER = true;
     // Transit standby to DA to replay logs
     try {
       UTIL2.getAdmin().transitReplicationPeerSyncReplicationState(PEER_ID,
         SyncReplicationState.DOWNGRADE_ACTIVE);
     } catch (Exception e) {
-      LOG.error("Failed to transit standby cluster to " + SyncReplicationState.DOWNGRADE_ACTIVE);
+      // we will kill master in the transit procedure's preCheck method, not in the rpc thread, so
+      // we can not know whether we could successfully get the returned proc id. If we can get the
+      // proc id, the call should be succeeded and we will not arrive here, and the below await
+      // check will pass immediately, if not, we will get this exception and then we need to rely on
+      // the below await check to make sure the transition is successfully finished.
+      LOG.warn("Failed to transit standby cluster to {}", SyncReplicationState.DOWNGRADE_ACTIVE);
     }
 
-    while (
-      UTIL2.getAdmin().getReplicationPeerSyncReplicationState(PEER_ID)
-          != SyncReplicationState.DOWNGRADE_ACTIVE
-    ) {
-      Thread.sleep(SLEEP_TIME);
-    }
+    await().atMost(Duration.ofMinutes(3))
+      .untilAsserted(() -> assertEquals(SyncReplicationState.DOWNGRADE_ACTIVE,
+        UTIL2.getAdmin().getReplicationPeerSyncReplicationState(PEER_ID)));
+
     verify(UTIL2, 0, COUNT);
   }
 }