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.replication.regionserver; 019 020import static org.junit.Assert.assertEquals; 021 022import java.io.IOException; 023import java.util.concurrent.CountDownLatch; 024import java.util.concurrent.ForkJoinPool; 025import java.util.concurrent.Future; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HConstants; 029import org.apache.hadoop.hbase.master.replication.DisablePeerProcedure; 030import org.apache.hadoop.hbase.procedure2.Procedure; 031import org.apache.hadoop.hbase.regionserver.HRegionServer; 032import org.apache.hadoop.hbase.replication.ReplicationPeer; 033import org.apache.hadoop.hbase.replication.ReplicationPeer.PeerState; 034import org.apache.hadoop.hbase.replication.TestReplicationBase; 035import org.apache.hadoop.hbase.testclassification.MasterTests; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.junit.ClassRule; 038import org.junit.Test; 039import org.junit.experimental.categories.Category; 040 041import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.PeerModificationState; 042 043/** 044 * This UT is used to make sure that we will not accidentally change the way to generate online 045 * servers. See HBASE-25774 and HBASE-25032 for more details. 046 */ 047@Category({ MasterTests.class, MediumTests.class }) 048public class TestRefreshPeerWhileRegionServerRestarts extends TestReplicationBase { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestRefreshPeerWhileRegionServerRestarts.class); 053 054 private static CountDownLatch ARRIVE; 055 056 private static CountDownLatch RESUME; 057 058 public static final class RegionServerForTest extends HRegionServer { 059 060 public RegionServerForTest(Configuration conf) throws IOException { 061 super(conf); 062 } 063 064 @Override 065 protected void tryRegionServerReport(long reportStartTime, long reportEndTime) 066 throws IOException { 067 if (ARRIVE != null) { 068 ARRIVE.countDown(); 069 ARRIVE = null; 070 try { 071 RESUME.await(); 072 } catch (InterruptedException e) { 073 } 074 } 075 super.tryRegionServerReport(reportStartTime, reportEndTime); 076 } 077 } 078 079 @Test 080 public void testRestart() throws Exception { 081 UTIL1.getMiniHBaseCluster().getConfiguration().setClass(HConstants.REGION_SERVER_IMPL, 082 RegionServerForTest.class, HRegionServer.class); 083 CountDownLatch arrive = new CountDownLatch(1); 084 ARRIVE = arrive; 085 RESUME = new CountDownLatch(1); 086 // restart a new region server, and wait until it finish initialization and want to call 087 // regionServerReport, so it will load the peer state to peer cache. 088 Future<HRegionServer> regionServerFuture = ForkJoinPool.commonPool() 089 .submit(() -> UTIL1.getMiniHBaseCluster().startRegionServer().getRegionServer()); 090 ARRIVE.await(); 091 // change the peer state, wait until it reach the last state, where we have already get the 092 // region server list for refreshing 093 Future<Void> future = hbaseAdmin.disableReplicationPeerAsync(PEER_ID2); 094 try { 095 UTIL1.waitFor(30000, () -> { 096 for (Procedure<?> proc : UTIL1.getMiniHBaseCluster().getMaster().getProcedures()) { 097 if (proc instanceof DisablePeerProcedure) { 098 return ((DisablePeerProcedure) proc).getCurrentStateId() 099 == PeerModificationState.POST_PEER_MODIFICATION_VALUE; 100 } 101 } 102 return false; 103 }); 104 } finally { 105 // let the new region server go 106 RESUME.countDown(); 107 } 108 // wait the disable peer operation to finish 109 future.get(); 110 // assert that the peer cache on the new region server has also been refreshed 111 ReplicationPeer peer = regionServerFuture.get().getReplicationSourceService() 112 .getReplicationManager().getReplicationPeers().getPeer(PEER_ID2); 113 assertEquals(PeerState.DISABLED, peer.getPeerState()); 114 } 115}