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.master;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.fail;
022
023import java.io.IOException;
024import java.util.AbstractMap.SimpleImmutableEntry;
025import java.util.List;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.HBaseTestingUtil;
028import org.apache.hadoop.hbase.TableName;
029import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
030import org.apache.hadoop.hbase.client.RegionInfo;
031import org.apache.hadoop.hbase.client.TableDescriptor;
032import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
033import org.apache.hadoop.hbase.master.assignment.RegionStates;
034import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
035import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot.SpaceQuotaStatus;
036import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy;
037import org.apache.hadoop.hbase.testclassification.MasterTests;
038import org.apache.hadoop.hbase.testclassification.MediumTests;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
041import org.apache.hadoop.hbase.util.PairOfSameType;
042import org.apache.hadoop.hbase.util.Threads;
043import org.junit.AfterClass;
044import org.junit.BeforeClass;
045import org.junit.ClassRule;
046import org.junit.Test;
047import org.junit.experimental.categories.Category;
048import org.slf4j.Logger;
049import org.slf4j.LoggerFactory;
050
051@Category({ MasterTests.class, MediumTests.class })
052public class TestMasterMetricsWrapper {
053
054  @ClassRule
055  public static final HBaseClassTestRule CLASS_RULE =
056    HBaseClassTestRule.forClass(TestMasterMetricsWrapper.class);
057
058  private static final Logger LOG = LoggerFactory.getLogger(TestMasterMetricsWrapper.class);
059
060  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
061  private static final int NUM_RS = 4;
062
063  @BeforeClass
064  public static void setup() throws Exception {
065    TEST_UTIL.startMiniCluster(NUM_RS);
066  }
067
068  @AfterClass
069  public static void teardown() throws Exception {
070    TEST_UTIL.shutdownMiniCluster();
071  }
072
073  @Test
074  public void testInfo() throws IOException {
075    HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
076    MetricsMasterWrapperImpl info = new MetricsMasterWrapperImpl(master);
077    assertEquals(master.getRegionNormalizerManager().getSplitPlanCount(), info.getSplitPlanCount(),
078      0);
079    assertEquals(master.getRegionNormalizerManager().getMergePlanCount(), info.getMergePlanCount(),
080      0);
081    assertEquals(master.getAverageLoad(), info.getAverageLoad(), 0);
082    assertEquals(master.getClusterId(), info.getClusterId());
083    assertEquals(master.getMasterActiveTime(), info.getActiveTime());
084    assertEquals(master.getMasterStartTime(), info.getStartTime());
085    assertEquals(master.getMasterCoprocessors().length, info.getCoprocessors().length);
086    assertEquals(master.getServerManager().getOnlineServersList().size(),
087      info.getNumRegionServers());
088    assertEquals(master.getMasterWalManager().getOldWALsDirSize(), info.getOldWALsDirSize());
089    int regionServerCount = NUM_RS;
090    assertEquals(regionServerCount, info.getNumRegionServers());
091
092    String zkServers = info.getZookeeperQuorum();
093    assertEquals(zkServers.split(",").length, TEST_UTIL.getZkCluster().getZooKeeperServerNum());
094
095    final int index = 3;
096    LOG.info("Stopping " + TEST_UTIL.getMiniHBaseCluster().getRegionServer(index));
097    TEST_UTIL.getMiniHBaseCluster().stopRegionServer(index, false);
098    TEST_UTIL.getMiniHBaseCluster().waitOnRegionServer(index);
099    // We stopped the regionserver but could take a while for the master to notice it so hang here
100    // until it does... then move forward to see if metrics wrapper notices.
101    while (
102      TEST_UTIL.getHBaseCluster().getMaster().getServerManager().getOnlineServers().size()
103          == regionServerCount
104    ) {
105      Threads.sleep(10);
106    }
107    assertEquals(regionServerCount - 1, info.getNumRegionServers());
108    assertEquals(1, info.getNumDeadRegionServers());
109    // now we do not expose this information as WALProcedureStore is not the only ProcedureStore
110    // implementation any more.
111    assertEquals(0, info.getNumWALFiles());
112    // We decommission the first online region server and verify the metrics.
113    TEST_UTIL.getMiniHBaseCluster().getMaster().decommissionRegionServers(
114      master.getServerManager().getOnlineServersList().subList(0, 1), false);
115    assertEquals(1, info.getNumDrainingRegionServers());
116    assertEquals(master.getServerManager().getOnlineServersList().get(0).toString(),
117      info.getDrainingRegionServers());
118  }
119
120  @Test
121  public void testQuotaSnapshotConversion() {
122    MetricsMasterWrapperImpl info =
123      new MetricsMasterWrapperImpl(TEST_UTIL.getHBaseCluster().getMaster());
124    assertEquals(new SimpleImmutableEntry<Long, Long>(1024L, 2048L), info
125      .convertSnapshot(new SpaceQuotaSnapshot(SpaceQuotaStatus.notInViolation(), 1024L, 2048L)));
126    assertEquals(new SimpleImmutableEntry<Long, Long>(4096L, 2048L), info.convertSnapshot(
127      new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 4096L, 2048L)));
128  }
129
130  /**
131   * tests online and offline region number
132   */
133  @Test
134  public void testOfflineRegion() throws Exception {
135    HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
136    MetricsMasterWrapperImpl info = new MetricsMasterWrapperImpl(master);
137    TableName table = TableName.valueOf("testRegionNumber");
138    try {
139      RegionInfo hri;
140      byte[] FAMILY = Bytes.toBytes("FAMILY");
141      TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(table)
142        .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build();
143      TEST_UTIL.getAdmin().createTable(tableDescriptor, Bytes.toBytes("A"), Bytes.toBytes("Z"), 5);
144
145      // wait till the table is assigned
146      long timeoutTime = EnvironmentEdgeManager.currentTime() + 1000;
147      while (true) {
148        List<RegionInfo> regions =
149          master.getAssignmentManager().getRegionStates().getRegionsOfTable(table);
150        if (regions.size() > 3) {
151          hri = regions.get(2);
152          break;
153        }
154        long now = EnvironmentEdgeManager.currentTime();
155        if (now > timeoutTime) {
156          fail("Could not find an online region");
157        }
158        Thread.sleep(10);
159      }
160
161      PairOfSameType<Integer> regionNumberPair = info.getRegionCounts();
162      assertEquals(5, regionNumberPair.getFirst().intValue());
163      assertEquals(0, regionNumberPair.getSecond().intValue());
164
165      TEST_UTIL.getAdmin().offline(hri.getRegionName());
166
167      timeoutTime = EnvironmentEdgeManager.currentTime() + 800;
168      RegionStates regionStates = master.getAssignmentManager().getRegionStates();
169      while (true) {
170        if (
171          regionStates.getRegionByStateOfTable(table).get(RegionState.State.OFFLINE).contains(hri)
172        ) {
173          break;
174        }
175        long now = EnvironmentEdgeManager.currentTime();
176        if (now > timeoutTime) {
177          fail("Failed to offline the region in time");
178          break;
179        }
180        Thread.sleep(10);
181      }
182      regionNumberPair = info.getRegionCounts();
183      assertEquals(4, regionNumberPair.getFirst().intValue());
184      assertEquals(1, regionNumberPair.getSecond().intValue());
185    } finally {
186      TEST_UTIL.deleteTable(table);
187    }
188  }
189}