|
| 1 | +/* |
| 2 | + * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | + * or more contributor license agreements. See the NOTICE file |
| 4 | + * distributed with this work for additional information |
| 5 | + * regarding copyright ownership. The ASF licenses this file |
| 6 | + * to you under the Apache License, Version 2.0 (the |
| 7 | + * "License"); you may not use this file except in compliance |
| 8 | + * with the License. You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | + */ |
| 18 | +package org.apache.hadoop.hbase.master; |
| 19 | + |
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
| 21 | + |
| 22 | +import java.util.concurrent.atomic.AtomicBoolean; |
| 23 | +import java.util.concurrent.atomic.AtomicInteger; |
| 24 | +import org.apache.hadoop.hbase.HBaseTestingUtil; |
| 25 | +import org.apache.hadoop.hbase.HConstants; |
| 26 | +import org.apache.hadoop.hbase.ServerName; |
| 27 | +import org.apache.hadoop.hbase.SingleProcessHBaseCluster; |
| 28 | +import org.apache.hadoop.hbase.StartTestingClusterOption; |
| 29 | +import org.apache.hadoop.hbase.TableName; |
| 30 | +import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; |
| 31 | +import org.apache.hadoop.hbase.client.TableDescriptor; |
| 32 | +import org.apache.hadoop.hbase.client.TableDescriptorBuilder; |
| 33 | +import org.apache.hadoop.hbase.master.hbck.HbckChore; |
| 34 | +import org.apache.hadoop.hbase.master.hbck.HbckReport; |
| 35 | +import org.apache.hadoop.hbase.regionserver.HRegion; |
| 36 | +import org.apache.hadoop.hbase.util.Bytes; |
| 37 | +import org.junit.jupiter.api.BeforeEach; |
| 38 | +import org.junit.jupiter.api.Test; |
| 39 | +import org.junit.jupiter.api.TestInfo; |
| 40 | +import org.slf4j.Logger; |
| 41 | +import org.slf4j.LoggerFactory; |
| 42 | + |
| 43 | +import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos; |
| 44 | + |
| 45 | +public abstract class AbstractTestMasterRegionMutation { |
| 46 | + |
| 47 | + private static final Logger LOG = LoggerFactory.getLogger(AbstractTestMasterRegionMutation.class); |
| 48 | + |
| 49 | + protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); |
| 50 | + protected static ServerName rs0; |
| 51 | + |
| 52 | + protected static final AtomicBoolean ERROR_OUT = new AtomicBoolean(false); |
| 53 | + protected static final AtomicInteger ERROR_COUNTER = new AtomicInteger(0); |
| 54 | + protected static final AtomicBoolean FIRST_TIME_ERROR = new AtomicBoolean(true); |
| 55 | + |
| 56 | + protected static void setUpBeforeClass(int numMasters, Class<? extends HRegion> regionImplClass) |
| 57 | + throws Exception { |
| 58 | + TEST_UTIL.getConfiguration().setClass(HConstants.REGION_IMPL, regionImplClass, HRegion.class); |
| 59 | + StartTestingClusterOption.Builder builder = StartTestingClusterOption.builder(); |
| 60 | + builder.numMasters(numMasters).numRegionServers(3); |
| 61 | + TEST_UTIL.startMiniCluster(builder.build()); |
| 62 | + SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); |
| 63 | + rs0 = cluster.getRegionServer(0).getServerName(); |
| 64 | + TEST_UTIL.getAdmin().balancerSwitch(false, true); |
| 65 | + } |
| 66 | + |
| 67 | + protected static void tearDownAfterClass() throws Exception { |
| 68 | + TEST_UTIL.shutdownMiniCluster(); |
| 69 | + } |
| 70 | + |
| 71 | + @BeforeEach |
| 72 | + protected void setUp(TestInfo testInfo) throws Exception { |
| 73 | + TableName tableName = TableName.valueOf(testInfo.getTestMethod().orElseThrow().getName()); |
| 74 | + TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName) |
| 75 | + .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build(); |
| 76 | + int startKey = 0; |
| 77 | + int endKey = 80000; |
| 78 | + TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9); |
| 79 | + } |
| 80 | + |
| 81 | + @Test |
| 82 | + protected void testMasterRegionMutations() throws Exception { |
| 83 | + HbckChore hbckChore = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster()); |
| 84 | + SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); |
| 85 | + |
| 86 | + int numRegions0 = cluster.getRegionServer(0).getNumberOfOnlineRegions(); |
| 87 | + int numRegions1 = cluster.getRegionServer(1).getNumberOfOnlineRegions(); |
| 88 | + int numRegions2 = cluster.getRegionServer(2).getNumberOfOnlineRegions(); |
| 89 | + |
| 90 | + hbckChore.choreForTesting(); |
| 91 | + HbckReport hbckReport = hbckChore.getLastReport(); |
| 92 | + assertEquals(0, hbckReport.getInconsistentRegions().size()); |
| 93 | + assertEquals(0, hbckReport.getOrphanRegionsOnFS().size()); |
| 94 | + assertEquals(0, hbckReport.getOrphanRegionsOnRS().size()); |
| 95 | + |
| 96 | + ERROR_OUT.set(true); |
| 97 | + TEST_UTIL.getAdmin().move( |
| 98 | + cluster.getRegionServer(1).getRegions().get(0).getRegionInfo().getEncodedNameAsBytes(), rs0); |
| 99 | + |
| 100 | + ERROR_OUT.set(true); |
| 101 | + TEST_UTIL.getAdmin().move( |
| 102 | + cluster.getRegionServer(2).getRegions().get(0).getRegionInfo().getEncodedNameAsBytes(), rs0); |
| 103 | + |
| 104 | + HMaster master = TEST_UTIL.getHBaseCluster().getMaster(); |
| 105 | + |
| 106 | + TEST_UTIL.waitFor(5000, 1000, () -> { |
| 107 | + LOG.info("numRegions0: {} , numRegions1: {} , numRegions2: {}", numRegions0, numRegions1, |
| 108 | + numRegions2); |
| 109 | + LOG.info("Online regions - server0 : {} , server1: {} , server2: {}", |
| 110 | + cluster.getRegionServer(0).getNumberOfOnlineRegions(), |
| 111 | + cluster.getRegionServer(1).getNumberOfOnlineRegions(), |
| 112 | + cluster.getRegionServer(2).getNumberOfOnlineRegions()); |
| 113 | + LOG.info("Num of successfully completed procedures: {} , num of all procedures: {}", |
| 114 | + master.getMasterProcedureExecutor().getProcedures().stream() |
| 115 | + .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState() |
| 116 | + == ProcedureProtos.ProcedureState.SUCCESS) |
| 117 | + .count(), |
| 118 | + master.getMasterProcedureExecutor().getProcedures().size()); |
| 119 | + return (numRegions0 + numRegions1 + numRegions2) |
| 120 | + == (cluster.getRegionServer(0).getNumberOfOnlineRegions() |
| 121 | + + cluster.getRegionServer(1).getNumberOfOnlineRegions() |
| 122 | + + cluster.getRegionServer(2).getNumberOfOnlineRegions()) |
| 123 | + && master.getMasterProcedureExecutor().getProcedures().stream() |
| 124 | + .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState() |
| 125 | + == ProcedureProtos.ProcedureState.SUCCESS) |
| 126 | + .count() == master.getMasterProcedureExecutor().getProcedures().size(); |
| 127 | + }); |
| 128 | + |
| 129 | + TEST_UTIL.waitFor(5000, 1000, () -> { |
| 130 | + HbckChore hbck = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster()); |
| 131 | + hbck.choreForTesting(); |
| 132 | + HbckReport report = hbck.getLastReport(); |
| 133 | + return report.getInconsistentRegions().isEmpty() && report.getOrphanRegionsOnFS().isEmpty() |
| 134 | + && report.getOrphanRegionsOnRS().isEmpty(); |
| 135 | + }); |
| 136 | + } |
| 137 | +} |
0 commit comments