Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.master; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Abortable; import org.apache.hadoop.hbase.CoordinatedStateException; import org.apache.hadoop.hbase.CoordinatedStateManager; import org.apache.hadoop.hbase.CoordinatedStateManagerFactory; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.MediumTests; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerLoad; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ZooKeeperConnectionException; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.catalog.MetaMockingUtil; import org.apache.hadoop.hbase.client.HConnection; import org.apache.hadoop.hbase.client.HConnectionTestingUtility; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.monitoring.MonitoredTask; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest; import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.util.Threads; import org.apache.hadoop.hbase.zookeeper.MetaRegionTracker; import org.apache.hadoop.hbase.zookeeper.ZKAssign; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.zookeeper.KeeperException; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.Mockito; import com.google.protobuf.ServiceException; /** * Standup the master and fake it to test various aspects of master function. * Does NOT spin up a mini hbase nor mini dfs cluster testing master (it does * put up a zk cluster but this is usually pretty fast compared). Also, should * be possible to inject faults at points difficult to get at in cluster context. * TODO: Speed up the zk connection by Master. It pauses 5 seconds establishing * session. */ @Category(MediumTests.class) public class TestMasterNoCluster { private static final Log LOG = LogFactory.getLog(TestMasterNoCluster.class); private static final HBaseTestingUtility TESTUTIL = new HBaseTestingUtility(); @BeforeClass public static void setUpBeforeClass() throws Exception { Configuration c = TESTUTIL.getConfiguration(); // We use local filesystem. Set it so it writes into the testdir. FSUtils.setRootDir(c, TESTUTIL.getDataTestDir()); DefaultMetricsSystem.setMiniClusterMode(true); // Startup a mini zk cluster. TESTUTIL.startMiniZKCluster(); } @AfterClass public static void tearDownAfterClass() throws Exception { TESTUTIL.shutdownMiniZKCluster(); } @After public void tearDown() throws KeeperException, ZooKeeperConnectionException, IOException { // Make sure zk is clean before we run the next test. ZooKeeperWatcher zkw = new ZooKeeperWatcher(TESTUTIL.getConfiguration(), "@Before", new Abortable() { @Override public void abort(String why, Throwable e) { throw new RuntimeException(why, e); } @Override public boolean isAborted() { return false; } }); ZKUtil.deleteNodeRecursively(zkw, zkw.baseZNode); zkw.close(); } /** * Test starting master then stopping it before its fully up. * @throws IOException * @throws KeeperException * @throws InterruptedException */ @Test(timeout = 30000) public void testStopDuringStart() throws IOException, KeeperException, InterruptedException { CoordinatedStateManager cp = CoordinatedStateManagerFactory .getCoordinatedStateManager(TESTUTIL.getConfiguration()); HMaster master = new HMaster(TESTUTIL.getConfiguration(), cp); master.start(); // Immediately have it stop. We used hang in assigning meta. master.stopMaster(); master.join(); } /** * Test master failover. * Start up three fake regionservers and a master. * @throws IOException * @throws KeeperException * @throws InterruptedException */ @Test(timeout = 30000) public void testFailover() throws IOException, KeeperException, InterruptedException, ServiceException { final long now = System.currentTimeMillis(); // Names for our three servers. Make the port numbers match hostname. // Will come in use down in the server when we need to figure how to respond. final ServerName sn0 = ServerName.valueOf("0.example.org", 0, now); final ServerName sn1 = ServerName.valueOf("1.example.org", 1, now); final ServerName sn2 = ServerName.valueOf("2.example.org", 2, now); final ServerName[] sns = new ServerName[] { sn0, sn1, sn2 }; // Put up the mock servers final Configuration conf = TESTUTIL.getConfiguration(); final MockRegionServer rs0 = new MockRegionServer(conf, sn0); final MockRegionServer rs1 = new MockRegionServer(conf, sn1); final MockRegionServer rs2 = new MockRegionServer(conf, sn2); // Put some data into the servers. Make it look like sn0 has the metaH // Put data into sn2 so it looks like it has a few regions for a table named 't'. MetaRegionTracker.setMetaLocation(rs0.getZooKeeper(), rs0.getServerName()); final TableName tableName = TableName.valueOf("t"); Result[] results = new Result[] { MetaMockingUtil.getMetaTableRowResult( new HRegionInfo(tableName, HConstants.EMPTY_START_ROW, HBaseTestingUtility.KEYS[1]), rs2.getServerName()), MetaMockingUtil.getMetaTableRowResult( new HRegionInfo(tableName, HBaseTestingUtility.KEYS[1], HBaseTestingUtility.KEYS[2]), rs2.getServerName()), MetaMockingUtil.getMetaTableRowResult( new HRegionInfo(tableName, HBaseTestingUtility.KEYS[2], HConstants.EMPTY_END_ROW), rs2.getServerName()) }; rs1.setNextResults(HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), results); // Create master. Subclass to override a few methods so we can insert mocks // and get notification on transitions. We need to fake out any rpcs the // master does opening/closing regions. Also need to fake out the address // of the 'remote' mocked up regionservers. CoordinatedStateManager cp = CoordinatedStateManagerFactory .getCoordinatedStateManager(TESTUTIL.getConfiguration()); HMaster master = new HMaster(conf, cp) { InetAddress getRemoteInetAddress(final int port, final long serverStartCode) throws UnknownHostException { // Return different address dependent on port passed. if (port > sns.length) { return super.getRemoteInetAddress(port, serverStartCode); } ServerName sn = sns[port]; return InetAddress.getByAddress(sn.getHostname(), new byte[] { 10, 0, 0, (byte) sn.getPort() }); } @Override ServerManager createServerManager(Server master, MasterServices services) throws IOException { ServerManager sm = super.createServerManager(master, services); // Spy on the created servermanager ServerManager spy = Mockito.spy(sm); // Fake a successful close. Mockito.doReturn(true).when(spy).sendRegionClose((ServerName) Mockito.any(), (HRegionInfo) Mockito.any(), Mockito.anyInt(), (ServerName) Mockito.any(), Mockito.anyBoolean()); return spy; } @Override protected CatalogTracker createCatalogTracker() throws IOException { // Insert a mock for the connection used by the CatalogTracker. Any // regionserver should do. Use TESTUTIL.getConfiguration rather than // the conf from the master; the conf will already have an HConnection // associate so the below mocking of a connection will fail. HConnection connection = HConnectionTestingUtility.getMockedConnectionAndDecorate( TESTUTIL.getConfiguration(), rs0, rs0, rs0.getServerName(), HRegionInfo.FIRST_META_REGIONINFO); return new CatalogTracker(getZooKeeper(), getConfiguration(), connection, this); } @Override void initNamespace() { } }; master.start(); try { // Wait till master is up ready for RPCs. while (!master.serviceStarted) Threads.sleep(10); // Fake master that there are regionservers out there. Report in. for (int i = 0; i < sns.length; i++) { RegionServerReportRequest.Builder request = RegionServerReportRequest.newBuilder(); ; ServerName sn = ServerName.parseVersionedServerName(sns[i].getVersionedBytes()); request.setServer(ProtobufUtil.toServerName(sn)); request.setLoad(ServerLoad.EMPTY_SERVERLOAD.obtainServerLoadPB()); master.getMasterRpcServices().regionServerReport(null, request.build()); } ZooKeeperWatcher zkw = master.getZooKeeper(); // Master should now come up. while (!master.isInitialized()) { // Fake meta is closed on rs0, try several times in case the event is lost // due to race with HMaster#assignMeta ZKAssign.transitionNodeClosed(zkw, HRegionInfo.FIRST_META_REGIONINFO, sn0, -1); Threads.sleep(100); } assertTrue(master.isInitialized()); } finally { rs0.stop("Test is done"); rs1.stop("Test is done"); rs2.stop("Test is done"); master.stopMaster(); master.join(); } } @Test public void testNotPullingDeadRegionServerFromZK() throws IOException, KeeperException, InterruptedException { final Configuration conf = TESTUTIL.getConfiguration(); final ServerName newServer = ServerName.valueOf("test.sample", 1, 101); final ServerName deadServer = ServerName.valueOf("test.sample", 1, 100); final MockRegionServer rs0 = new MockRegionServer(conf, newServer); CoordinatedStateManager cp = CoordinatedStateManagerFactory .getCoordinatedStateManager(TESTUTIL.getConfiguration()); HMaster master = new HMaster(conf, cp) { @Override void assignMeta(MonitoredTask status, Set<ServerName> previouslyFailedMeatRSs) { } @Override void initializeZKBasedSystemTrackers() throws IOException, InterruptedException, KeeperException, CoordinatedStateException { super.initializeZKBasedSystemTrackers(); // Record a newer server in server manager at first serverManager.recordNewServerWithLock(newServer, ServerLoad.EMPTY_SERVERLOAD); List<ServerName> onlineServers = new ArrayList<ServerName>(); onlineServers.add(deadServer); onlineServers.add(newServer); // Mock the region server tracker to pull the dead server from zk regionServerTracker = Mockito.spy(regionServerTracker); Mockito.doReturn(onlineServers).when(regionServerTracker).getOnlineServers(); } @Override protected CatalogTracker createCatalogTracker() throws IOException { // Insert a mock for the connection used by the CatalogTracker. Any // regionserver should do. Use TESTUTIL.getConfiguration rather than // the conf from the master; the conf will already have an HConnection // associate so the below mocking of a connection will fail. HConnection connection = HConnectionTestingUtility.getMockedConnectionAndDecorate( TESTUTIL.getConfiguration(), rs0, rs0, rs0.getServerName(), HRegionInfo.FIRST_META_REGIONINFO); return new CatalogTracker(getZooKeeper(), getConfiguration(), connection, this); } @Override void initNamespace() { } }; master.start(); try { // Wait till master is initialized. while (!master.initialized) Threads.sleep(10); LOG.info("Master is initialized"); assertFalse("The dead server should not be pulled in", master.serverManager.isServerOnline(deadServer)); } finally { master.stopMaster(); master.join(); } } }