001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master.replication; 019 020import java.io.IOException; 021import org.apache.hadoop.hbase.HBaseClassTestRule; 022import org.apache.hadoop.hbase.HBaseTestingUtil; 023import org.apache.hadoop.hbase.ProcedureTestUtil; 024import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 025import org.apache.hadoop.hbase.procedure2.Procedure; 026import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 027import org.apache.hadoop.hbase.replication.ReplicationException; 028import org.apache.hadoop.hbase.replication.SyncReplicationState; 029import org.apache.hadoop.hbase.testclassification.LargeTests; 030import org.apache.hadoop.hbase.testclassification.MasterTests; 031import org.junit.AfterClass; 032import org.junit.BeforeClass; 033import org.junit.ClassRule; 034import org.junit.Test; 035import org.junit.experimental.categories.Category; 036 037@Category({ MasterTests.class, LargeTests.class }) 038public class TestTransitPeerSyncReplicationStateProcedureBackoff { 039 040 @ClassRule 041 public static final HBaseClassTestRule CLASS_RULE = 042 HBaseClassTestRule.forClass(TestTransitPeerSyncReplicationStateProcedureBackoff.class); 043 044 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 045 046 private static boolean FAIL = true; 047 048 public static class TestTransitPeerSyncReplicationStateProcedure 049 extends TransitPeerSyncReplicationStateProcedure { 050 051 public TestTransitPeerSyncReplicationStateProcedure() { 052 } 053 054 public TestTransitPeerSyncReplicationStateProcedure(String peerId, SyncReplicationState state) { 055 super(peerId, state); 056 } 057 058 private void tryFail() throws ReplicationException { 059 synchronized (TestTransitPeerSyncReplicationStateProcedureBackoff.class) { 060 if (FAIL) { 061 throw new ReplicationException("Inject error"); 062 } 063 FAIL = true; 064 } 065 } 066 067 @Override 068 protected <T extends Procedure<MasterProcedureEnv>> void 069 addChildProcedure(@SuppressWarnings("unchecked") T... subProcedure) { 070 // Make it a no-op 071 } 072 073 @Override 074 protected void preTransit(MasterProcedureEnv env) throws IOException { 075 fromState = SyncReplicationState.DOWNGRADE_ACTIVE; 076 } 077 078 @Override 079 protected void setPeerNewSyncReplicationState(MasterProcedureEnv env) 080 throws ReplicationException { 081 tryFail(); 082 } 083 084 @Override 085 protected void removeAllReplicationQueues(MasterProcedureEnv env) throws ReplicationException { 086 tryFail(); 087 } 088 089 @Override 090 protected void reopenRegions(MasterProcedureEnv env) { 091 // do nothing; 092 } 093 094 @Override 095 protected void transitPeerSyncReplicationState(MasterProcedureEnv env) 096 throws ReplicationException { 097 tryFail(); 098 } 099 100 @Override 101 protected void createDirForRemoteWAL(MasterProcedureEnv env) throws IOException { 102 try { 103 tryFail(); 104 } catch (ReplicationException e) { 105 throw new IOException(e); 106 } 107 } 108 } 109 110 @BeforeClass 111 public static void setUp() throws Exception { 112 UTIL.startMiniCluster(1); 113 } 114 115 @AfterClass 116 public static void tearDown() throws Exception { 117 UTIL.shutdownMiniCluster(); 118 } 119 120 private void assertBackoffIncrease() throws IOException, InterruptedException { 121 ProcedureTestUtil.waitUntilProcedureWaitingTimeout(UTIL, 122 TestTransitPeerSyncReplicationStateProcedure.class, 30000); 123 ProcedureTestUtil.waitUntilProcedureTimeoutIncrease(UTIL, 124 TestTransitPeerSyncReplicationStateProcedure.class, 2); 125 synchronized (TestTransitPeerSyncReplicationStateProcedure.class) { 126 FAIL = false; 127 } 128 UTIL.waitFor(30000, () -> FAIL); 129 } 130 131 @Test 132 public void testDowngradeActiveToActive() throws IOException, InterruptedException { 133 ProcedureExecutor<MasterProcedureEnv> procExec = 134 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor(); 135 // Test procedure: DOWNGRADE_ACTIVE ==> ACTIVE 136 long procId = procExec.submitProcedure( 137 new TestTransitPeerSyncReplicationStateProcedure("1", SyncReplicationState.ACTIVE)); 138 // No retry for PRE_PEER_SYNC_REPLICATION_STATE_TRANSITION 139 // SET_PEER_NEW_SYNC_REPLICATION_STATE 140 assertBackoffIncrease(); 141 // No retry for REFRESH_PEER_SYNC_REPLICATION_STATE_ON_RS_BEGIN 142 // No retry for REOPEN_ALL_REGIONS_IN_PEER 143 // TRANSIT_PEER_NEW_SYNC_REPLICATION_STATE 144 assertBackoffIncrease(); 145 // No retry for REFRESH_PEER_SYNC_REPLICATION_STATE_ON_RS_END 146 // No retry for POST_PEER_SYNC_REPLICATION_STATE_TRANSITION 147 UTIL.waitFor(30000, () -> procExec.isFinished(procId)); 148 } 149 150 @Test 151 public void testDowngradeActiveToStandby() throws IOException, InterruptedException { 152 ProcedureExecutor<MasterProcedureEnv> procExec = 153 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor(); 154 // Test procedure: DOWNGRADE_ACTIVE ==> ACTIVE 155 long procId = procExec.submitProcedure( 156 new TestTransitPeerSyncReplicationStateProcedure("2", SyncReplicationState.STANDBY)); 157 // No retry for PRE_PEER_SYNC_REPLICATION_STATE_TRANSITION 158 // SET_PEER_NEW_SYNC_REPLICATION_STATE 159 assertBackoffIncrease(); 160 // No retry for REFRESH_PEER_SYNC_REPLICATION_STATE_ON_RS_BEGIN 161 // REMOVE_ALL_REPLICATION_QUEUES_IN_PEER 162 assertBackoffIncrease(); 163 // TRANSIT_PEER_NEW_SYNC_REPLICATION_STATE 164 assertBackoffIncrease(); 165 // No retry for REFRESH_PEER_SYNC_REPLICATION_STATE_ON_RS_END 166 // CREATE_DIR_FOR_REMOTE_WAL 167 assertBackoffIncrease(); 168 // No retry for POST_PEER_SYNC_REPLICATION_STATE_TRANSITION 169 UTIL.waitFor(30000, () -> procExec.isFinished(procId)); 170 } 171}