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; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertNull; 022import static org.junit.jupiter.api.Assertions.assertThrows; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024 025import java.io.IOException; 026import org.apache.hadoop.hbase.master.RegionState; 027import org.apache.hadoop.hbase.testclassification.MediumTests; 028import org.apache.hadoop.hbase.testclassification.MiscTests; 029import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 030import org.apache.hadoop.hbase.util.Threads; 031import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; 032import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 033import org.apache.zookeeper.KeeperException; 034import org.junit.jupiter.api.AfterAll; 035import org.junit.jupiter.api.AfterEach; 036import org.junit.jupiter.api.BeforeAll; 037import org.junit.jupiter.api.BeforeEach; 038import org.junit.jupiter.api.Tag; 039import org.junit.jupiter.api.Test; 040import org.mockito.Mockito; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; 045import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 046 047import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; 048import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.GetRequest; 049import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.GetResponse; 050 051/** 052 * Test {@link org.apache.hadoop.hbase.zookeeper.MetaTableLocator} 053 */ 054@Tag(MiscTests.TAG) 055@Tag(MediumTests.TAG) 056public class TestMetaTableLocator { 057 058 private static final Logger LOG = LoggerFactory.getLogger(TestMetaTableLocator.class); 059 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 060 private static final ServerName SN = 061 ServerName.valueOf("example.org", 1234, EnvironmentEdgeManager.currentTime()); 062 private ZKWatcher watcher; 063 private Abortable abortable; 064 065 @BeforeAll 066 public static void beforeClass() throws Exception { 067 // Set this down so tests run quicker 068 UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3); 069 UTIL.startMiniZKCluster(); 070 } 071 072 @AfterAll 073 public static void afterClass() throws IOException { 074 UTIL.getZkCluster().shutdown(); 075 } 076 077 @BeforeEach 078 public void before() throws IOException { 079 this.abortable = new Abortable() { 080 @Override 081 public void abort(String why, Throwable e) { 082 LOG.info(why, e); 083 } 084 085 @Override 086 public boolean isAborted() { 087 return false; 088 } 089 }; 090 this.watcher = 091 new ZKWatcher(UTIL.getConfiguration(), this.getClass().getSimpleName(), this.abortable, true); 092 } 093 094 @AfterEach 095 public void after() { 096 try { 097 // Clean out meta location or later tests will be confused... they presume 098 // start fresh in zk. 099 MetaTableLocator.deleteMetaLocation(this.watcher); 100 } catch (KeeperException e) { 101 LOG.warn("Unable to delete hbase:meta location", e); 102 } 103 104 this.watcher.close(); 105 } 106 107 /** 108 * Test normal operations 109 */ 110 @Test 111 public void testMetaLookup() 112 throws IOException, InterruptedException, ServiceException, KeeperException { 113 final ClientProtos.ClientService.BlockingInterface client = 114 Mockito.mock(ClientProtos.ClientService.BlockingInterface.class); 115 116 Mockito.when(client.get((RpcController) Mockito.any(), (GetRequest) Mockito.any())) 117 .thenReturn(GetResponse.newBuilder().build()); 118 119 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 120 for (RegionState.State state : RegionState.State.values()) { 121 if (state.equals(RegionState.State.OPEN)) { 122 continue; 123 } 124 MetaTableLocator.setMetaLocation(this.watcher, SN, state); 125 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 126 assertEquals(state, MetaTableLocator.getMetaRegionState(this.watcher).getState()); 127 } 128 MetaTableLocator.setMetaLocation(this.watcher, SN, RegionState.State.OPEN); 129 assertEquals(SN, MetaTableLocator.getMetaRegionLocation(this.watcher)); 130 assertEquals(RegionState.State.OPEN, 131 MetaTableLocator.getMetaRegionState(this.watcher).getState()); 132 133 MetaTableLocator.deleteMetaLocation(this.watcher); 134 assertNull(MetaTableLocator.getMetaRegionState(this.watcher).getServerName()); 135 assertEquals(RegionState.State.OFFLINE, 136 MetaTableLocator.getMetaRegionState(this.watcher).getState()); 137 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 138 } 139 140 @Test 141 public void testTimeoutWaitForMeta() throws IOException, InterruptedException { 142 assertThrows(NotAllMetaRegionsOnlineException.class, () -> { 143 MetaTableLocator.waitMetaRegionLocation(watcher, 100); 144 }); 145 } 146 147 /** 148 * Test waiting on meat w/ no timeout specified. 149 */ 150 @Test 151 public void testNoTimeoutWaitForMeta() throws IOException, InterruptedException, KeeperException { 152 ServerName hsa = MetaTableLocator.getMetaRegionLocation(watcher); 153 assertNull(hsa); 154 155 // Now test waiting on meta location getting set. 156 Thread t = new WaitOnMetaThread(); 157 startWaitAliveThenWaitItLives(t, 1); 158 // Set a meta location. 159 MetaTableLocator.setMetaLocation(this.watcher, SN, RegionState.State.OPEN); 160 hsa = SN; 161 // Join the thread... should exit shortly. 162 t.join(); 163 // Now meta is available. 164 assertTrue(MetaTableLocator.getMetaRegionLocation(watcher).equals(hsa)); 165 } 166 167 private void startWaitAliveThenWaitItLives(final Thread t, final int ms) { 168 t.start(); 169 UTIL.waitFor(2000, t::isAlive); 170 // Wait one second. 171 Threads.sleep(ms); 172 assertTrue(t.isAlive(), "Assert " + t.getName() + " still waiting"); 173 } 174 175 /** 176 * Wait on META. 177 */ 178 class WaitOnMetaThread extends Thread { 179 180 WaitOnMetaThread() { 181 super("WaitOnMeta"); 182 } 183 184 @Override 185 public void run() { 186 try { 187 doWaiting(); 188 } catch (InterruptedException e) { 189 throw new RuntimeException("Failed wait", e); 190 } 191 LOG.info("Exiting " + getName()); 192 } 193 194 void doWaiting() throws InterruptedException { 195 try { 196 for (;;) { 197 if (MetaTableLocator.waitMetaRegionLocation(watcher, 10000) != null) { 198 break; 199 } 200 } 201 } catch (NotAllMetaRegionsOnlineException e) { 202 // Ignore 203 } 204 } 205 } 206}