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.Threads; 029import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; 030import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 031import org.apache.zookeeper.KeeperException; 032import org.junit.After; 033import org.junit.AfterClass; 034import org.junit.Before; 035import org.junit.BeforeClass; 036import org.junit.ClassRule; 037import org.junit.Test; 038import org.junit.experimental.categories.Category; 039import org.mockito.Mockito; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; 044import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 045 046import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; 047import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.GetRequest; 048import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.GetResponse; 049 050/** 051 * Test {@link org.apache.hadoop.hbase.zookeeper.MetaTableLocator} 052 */ 053@Category({ MiscTests.class, MediumTests.class }) 054public class TestMetaTableLocator { 055 056 @ClassRule 057 public static final HBaseClassTestRule CLASS_RULE = 058 HBaseClassTestRule.forClass(TestMetaTableLocator.class); 059 060 private static final Logger LOG = LoggerFactory.getLogger(TestMetaTableLocator.class); 061 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 062 private static final ServerName SN = 063 ServerName.valueOf("example.org", 1234, System.currentTimeMillis()); 064 private ZKWatcher watcher; 065 private Abortable abortable; 066 067 @BeforeClass 068 public static void beforeClass() throws Exception { 069 // Set this down so tests run quicker 070 UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3); 071 UTIL.startMiniZKCluster(); 072 } 073 074 @AfterClass 075 public static void afterClass() throws IOException { 076 UTIL.getZkCluster().shutdown(); 077 } 078 079 @Before 080 public void before() throws IOException { 081 this.abortable = new Abortable() { 082 @Override 083 public void abort(String why, Throwable e) { 084 LOG.info(why, e); 085 } 086 087 @Override 088 public boolean isAborted() { 089 return false; 090 } 091 }; 092 this.watcher = 093 new ZKWatcher(UTIL.getConfiguration(), this.getClass().getSimpleName(), this.abortable, true); 094 } 095 096 @After 097 public void after() { 098 try { 099 // Clean out meta location or later tests will be confused... they presume 100 // start fresh in zk. 101 MetaTableLocator.deleteMetaLocation(this.watcher); 102 } catch (KeeperException e) { 103 LOG.warn("Unable to delete hbase:meta location", e); 104 } 105 106 this.watcher.close(); 107 } 108 109 /** 110 * Test normal operations 111 */ 112 @Test 113 public void testMetaLookup() 114 throws IOException, InterruptedException, ServiceException, KeeperException { 115 final ClientProtos.ClientService.BlockingInterface client = 116 Mockito.mock(ClientProtos.ClientService.BlockingInterface.class); 117 118 Mockito.when(client.get((RpcController) Mockito.any(), (GetRequest) Mockito.any())) 119 .thenReturn(GetResponse.newBuilder().build()); 120 121 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 122 for (RegionState.State state : RegionState.State.values()) { 123 if (state.equals(RegionState.State.OPEN)) { 124 continue; 125 } 126 MetaTableLocator.setMetaLocation(this.watcher, SN, state); 127 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 128 assertEquals(state, MetaTableLocator.getMetaRegionState(this.watcher).getState()); 129 } 130 MetaTableLocator.setMetaLocation(this.watcher, SN, RegionState.State.OPEN); 131 assertEquals(SN, MetaTableLocator.getMetaRegionLocation(this.watcher)); 132 assertEquals(RegionState.State.OPEN, 133 MetaTableLocator.getMetaRegionState(this.watcher).getState()); 134 135 MetaTableLocator.deleteMetaLocation(this.watcher); 136 assertNull(MetaTableLocator.getMetaRegionState(this.watcher).getServerName()); 137 assertEquals(RegionState.State.OFFLINE, 138 MetaTableLocator.getMetaRegionState(this.watcher).getState()); 139 assertNull(MetaTableLocator.getMetaRegionLocation(this.watcher)); 140 } 141 142 @Test(expected = NotAllMetaRegionsOnlineException.class) 143 public void testTimeoutWaitForMeta() throws IOException, InterruptedException { 144 MetaTableLocator.waitMetaRegionLocation(watcher, 100); 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("Assert " + t.getName() + " still waiting", t.isAlive()); 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}