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