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.jupiter.api.Assertions.assertEquals;
021
022import java.io.IOException;
023import java.util.stream.Stream;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
026import org.apache.hadoop.hbase.HBaseTestingUtil;
027import org.apache.hadoop.hbase.HConstants;
028import org.apache.hadoop.hbase.TableName;
029import org.apache.hadoop.hbase.client.TableDescriptor;
030import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
031import org.apache.hadoop.hbase.testclassification.MediumTests;
032import org.apache.hadoop.hbase.testclassification.RegionServerTests;
033import org.apache.hadoop.hbase.util.Bytes;
034import org.apache.hadoop.hbase.util.RegionSplitter;
035import org.junit.jupiter.api.AfterAll;
036import org.junit.jupiter.api.AfterEach;
037import org.junit.jupiter.api.BeforeAll;
038import org.junit.jupiter.api.BeforeEach;
039import org.junit.jupiter.api.Tag;
040import org.junit.jupiter.api.TestInfo;
041import org.junit.jupiter.api.TestTemplate;
042import org.junit.jupiter.params.provider.Arguments;
043
044@Tag(RegionServerTests.TAG)
045@Tag(MediumTests.TAG)
046@HBaseParameterizedTestTemplate(name = "{index}: disableBeforeModifying={0}")
047public class TestRegionReplicasWithModifyTable {
048
049  private static final int NB_SERVERS = 3;
050
051  private static final HBaseTestingUtil HTU = new HBaseTestingUtil();
052  private static final byte[] f = HConstants.CATALOG_FAMILY;
053
054  private final boolean disableBeforeModifying;
055
056  private TableName tableName;
057
058  public static Stream<Arguments> parameters() {
059    return Stream.of(Arguments.of(true), Arguments.of(false));
060  }
061
062  public TestRegionReplicasWithModifyTable(boolean disableBeforeModifying) {
063    this.disableBeforeModifying = disableBeforeModifying;
064  }
065
066  @BeforeAll
067  public static void before() throws Exception {
068    HTU.startMiniCluster(NB_SERVERS);
069  }
070
071  @BeforeEach
072  public void setUp(TestInfo testInfo) {
073    tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());
074  }
075
076  private void enableReplicationByModification(boolean withReplica, int initialReplicaCount,
077    int enableReplicaCount, int splitCount) throws IOException, InterruptedException {
078    TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName);
079    if (withReplica) {
080      builder.setRegionReplication(initialReplicaCount);
081    }
082    TableDescriptor htd = builder.build();
083    if (splitCount > 0) {
084      byte[][] splits = getSplits(splitCount);
085      HTU.createTable(htd, new byte[][] { f }, splits, new Configuration(HTU.getConfiguration()));
086    } else {
087      HTU.createTable(htd, new byte[][] { f }, (byte[][]) null,
088        new Configuration(HTU.getConfiguration()));
089    }
090    if (disableBeforeModifying) {
091      HTU.getAdmin().disableTable(tableName);
092    }
093    HBaseTestingUtil.setReplicas(HTU.getAdmin(), tableName, enableReplicaCount);
094    if (disableBeforeModifying) {
095      HTU.getAdmin().enableTable(tableName);
096    }
097    int expectedRegionCount;
098    if (splitCount > 0) {
099      expectedRegionCount = enableReplicaCount * splitCount;
100    } else {
101      expectedRegionCount = enableReplicaCount;
102    }
103    assertTotalRegions(expectedRegionCount);
104  }
105
106  private static byte[][] getSplits(int numRegions) {
107    RegionSplitter.UniformSplit split = new RegionSplitter.UniformSplit();
108    split.setFirstRow(Bytes.toBytes(0L));
109    split.setLastRow(Bytes.toBytes(Long.MAX_VALUE));
110    return split.split(numRegions);
111  }
112
113  @AfterAll
114  public static void afterClass() throws Exception {
115    HTU.shutdownMiniCluster();
116  }
117
118  @AfterEach
119  public void tearDown() throws IOException {
120    HTU.getAdmin().disableTable(tableName);
121    HTU.getAdmin().deleteTable(tableName);
122  }
123
124  private void assertTotalRegions(int expected) {
125    int actual = HTU.getHBaseCluster().getRegions(tableName).size();
126    assertEquals(expected, actual);
127  }
128
129  @TestTemplate
130  public void testRegionReplicasUsingEnableTable() throws Exception {
131    enableReplicationByModification(false, 0, 3, 0);
132  }
133
134  @TestTemplate
135  public void testRegionReplicasUsingEnableTableForMultipleRegions() throws Exception {
136    enableReplicationByModification(false, 0, 3, 10);
137  }
138
139  @TestTemplate
140  public void testRegionReplicasByEnableTableWhenReplicaCountIsIncreased() throws Exception {
141    enableReplicationByModification(true, 2, 3, 0);
142  }
143
144  @TestTemplate
145  public void testRegionReplicasByEnableTableWhenReplicaCountIsDecreased() throws Exception {
146    enableReplicationByModification(true, 3, 2, 0);
147  }
148
149  @TestTemplate
150  public void testRegionReplicasByEnableTableWhenReplicaCountIsDecreasedWithMultipleRegions()
151    throws Exception {
152    enableReplicationByModification(true, 3, 2, 20);
153  }
154
155  @TestTemplate
156  public void testRegionReplicasByEnableTableWhenReplicaCountIsIncreasedWithMultipleRegions()
157    throws Exception {
158    enableReplicationByModification(true, 2, 3, 15);
159  }
160}