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.regionserver;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023
024import java.io.IOException;
025import java.util.ArrayList;
026import java.util.Collection;
027
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.HBaseTestingUtility;
031import org.apache.hadoop.hbase.HConstants;
032import org.apache.hadoop.hbase.ServerName;
033import org.apache.hadoop.hbase.TableName;
034import org.apache.hadoop.hbase.client.RegionInfo;
035import org.apache.hadoop.hbase.client.RegionReplicaUtil;
036import org.apache.hadoop.hbase.client.Table;
037import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
038import org.apache.hadoop.hbase.testclassification.MediumTests;
039import org.apache.hadoop.hbase.testclassification.RegionServerTests;
040import org.apache.hadoop.hbase.util.Bytes;
041import org.apache.hadoop.hbase.util.RegionSplitter;
042import org.junit.After;
043import org.junit.AfterClass;
044import org.junit.Before;
045import org.junit.BeforeClass;
046import org.junit.ClassRule;
047import org.junit.Rule;
048import org.junit.Test;
049import org.junit.experimental.categories.Category;
050import org.junit.rules.TestName;
051import org.slf4j.Logger;
052import org.slf4j.LoggerFactory;
053
054@Category({RegionServerTests.class, MediumTests.class})
055public class TestRegionReplicasWithRestartScenarios {
056
057  @ClassRule
058  public static final HBaseClassTestRule CLASS_RULE =
059      HBaseClassTestRule.forClass(TestRegionReplicasWithRestartScenarios.class);
060
061  private static final Logger LOG =
062      LoggerFactory.getLogger(TestRegionReplicasWithRestartScenarios.class);
063
064  @Rule public TestName name = new TestName();
065
066  private static final int NB_SERVERS = 3;
067  private Table table;
068  private TableName tableName;
069
070  private static final HBaseTestingUtility HTU = new HBaseTestingUtility();
071  private static final byte[] f = HConstants.CATALOG_FAMILY;
072
073  @BeforeClass
074  public static void beforeClass() throws Exception {
075    HTU.getConfiguration().setInt("hbase.master.wait.on.regionservers.mintostart", NB_SERVERS);
076    HTU.startMiniCluster(NB_SERVERS);
077  }
078
079  @Before
080  public void before() throws IOException {
081    this.tableName = TableName.valueOf(this.name.getMethodName());
082    this.table = createTableDirectlyFromHTD(this.tableName);
083  }
084
085  @After
086  public void after() throws IOException {
087    this.table.close();
088    HTU.deleteTable(this.tableName);
089  }
090
091  private static Table createTableDirectlyFromHTD(final TableName tableName) throws IOException {
092    TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName);
093    builder.setRegionReplication(3);
094    return HTU.createTable(builder.build(), new byte[][] { f }, getSplits(20),
095      new Configuration(HTU.getConfiguration()));
096  }
097
098  private static byte[][] getSplits(int numRegions) {
099    RegionSplitter.UniformSplit split = new RegionSplitter.UniformSplit();
100    split.setFirstRow(Bytes.toBytes(0L));
101    split.setLastRow(Bytes.toBytes(Long.MAX_VALUE));
102    return split.split(numRegions);
103  }
104
105  @AfterClass
106  public static void afterClass() throws Exception {
107    HRegionServer.TEST_SKIP_REPORTING_TRANSITION = false;
108    HTU.shutdownMiniCluster();
109  }
110
111  private HRegionServer getRS() {
112    return HTU.getMiniHBaseCluster().getRegionServer(0);
113  }
114
115  private HRegionServer getSecondaryRS() {
116    return HTU.getMiniHBaseCluster().getRegionServer(1);
117  }
118
119  private HRegionServer getTertiaryRS() {
120    return HTU.getMiniHBaseCluster().getRegionServer(2);
121  }
122
123  @Test
124  public void testRegionReplicasCreated() throws Exception {
125    assertReplicaDistributed();
126  }
127
128  @Test
129  public void testWhenRestart() throws Exception {
130    ServerName serverName = getRS().getServerName();
131    HTU.getHBaseCluster().stopRegionServer(serverName);
132    HTU.getHBaseCluster().waitForRegionServerToStop(serverName, 60000);
133    HTU.getHBaseCluster().startRegionServerAndWait(60000);
134    HTU.waitTableAvailable(this.tableName);
135    assertReplicaDistributed();
136  }
137
138  private void assertReplicaDistributed() throws Exception {
139    Collection<HRegion> onlineRegions = getRS().getOnlineRegionsLocalContext();
140    boolean res = checkDuplicates(onlineRegions);
141    assertFalse(res);
142    Collection<HRegion> onlineRegions2 = getSecondaryRS().getOnlineRegionsLocalContext();
143    res = checkDuplicates(onlineRegions2);
144    assertFalse(res);
145    Collection<HRegion> onlineRegions3 = getTertiaryRS().getOnlineRegionsLocalContext();
146    checkDuplicates(onlineRegions3);
147    assertFalse(res);
148    int totalRegions = onlineRegions.size() + onlineRegions2.size() + onlineRegions3.size();
149    assertEquals(62, totalRegions);
150  }
151
152  private boolean checkDuplicates(Collection<HRegion> onlineRegions3) throws Exception {
153    ArrayList<Region> copyOfRegion = new ArrayList<Region>(onlineRegions3);
154    for (Region region : copyOfRegion) {
155      RegionInfo regionInfo = region.getRegionInfo();
156      RegionInfo regionInfoForReplica =
157          RegionReplicaUtil.getRegionInfoForDefaultReplica(regionInfo);
158      int i = 0;
159      for (Region actualRegion : onlineRegions3) {
160        if (regionInfoForReplica.equals(
161          RegionReplicaUtil.getRegionInfoForDefaultReplica(actualRegion.getRegionInfo()))) {
162          i++;
163          if (i > 1) {
164            LOG.warn("Duplicate found {} and {}", actualRegion.getRegionInfo(),
165                region.getRegionInfo());
166            assertTrue(Bytes.equals(region.getRegionInfo().getStartKey(),
167              actualRegion.getRegionInfo().getStartKey()));
168            assertTrue(Bytes.equals(region.getRegionInfo().getEndKey(),
169              actualRegion.getRegionInfo().getEndKey()));
170            return true;
171          }
172        }
173      }
174    }
175    return false;
176  }
177}