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