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.assertFalse; 022import static org.junit.Assert.assertTrue; 023 024import java.io.IOException; 025import java.util.Arrays; 026import java.util.List; 027 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.MetaTableAccessor; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.Put; 034import org.apache.hadoop.hbase.client.RegionInfo; 035import org.apache.hadoop.hbase.client.RegionInfoBuilder; 036import org.apache.hadoop.hbase.testclassification.LargeTests; 037import org.apache.hadoop.hbase.testclassification.MasterTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.junit.After; 040import org.junit.Before; 041import org.junit.ClassRule; 042import org.junit.Rule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.junit.rules.TestName; 046 047@Category({MasterTests.class, LargeTests.class}) 048public class TestCatalogJanitorCluster { 049 @ClassRule 050 public static final HBaseClassTestRule CLASS_RULE = 051 HBaseClassTestRule.forClass(TestCatalogJanitorCluster.class); 052 053 @Rule 054 public final TestName name = new TestName(); 055 056 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 057 private static final TableName T1 = TableName.valueOf("t1"); 058 private static final TableName T2 = TableName.valueOf("t2"); 059 private static final TableName T3 = TableName.valueOf("t3"); 060 061 @Before 062 public void before() throws Exception { 063 TEST_UTIL.startMiniCluster(); 064 TEST_UTIL.createMultiRegionTable(T1, new byte [][] {HConstants.CATALOG_FAMILY}); 065 TEST_UTIL.createMultiRegionTable(T2, new byte [][] {HConstants.CATALOG_FAMILY}); 066 TEST_UTIL.createMultiRegionTable(T3, new byte [][] {HConstants.CATALOG_FAMILY}); 067 } 068 069 @After 070 public void after() throws Exception { 071 TEST_UTIL.shutdownMiniCluster(); 072 } 073 074 /** 075 * Fat method where we start with a fat hbase:meta and then gradually intro 076 * problems running catalogjanitor for each to ensure it triggers complaint. 077 * Do one big method because takes a while to build up the context we need. 078 * We create three tables and then make holes, overlaps, add unknown servers 079 * and empty out regioninfo columns. Each should up counts in the 080 * CatalogJanitor.Report produced. 081 */ 082 @Test 083 public void testConsistency() throws IOException { 084 CatalogJanitor janitor = TEST_UTIL.getHBaseCluster().getMaster().getCatalogJanitor(); 085 int gc = janitor.scan(); 086 CatalogJanitor.Report report = janitor.getLastReport(); 087 // Assert no problems. 088 assertTrue(report.isEmpty()); 089 // Now remove first region in table t2 to see if catalogjanitor scan notices. 090 List<RegionInfo> t2Ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), T2); 091 MetaTableAccessor.deleteRegionInfo(TEST_UTIL.getConnection(), t2Ris.get(0)); 092 gc = janitor.scan(); 093 report = janitor.getLastReport(); 094 assertFalse(report.isEmpty()); 095 assertEquals(1, report.getHoles().size()); 096 assertTrue(report.getHoles().get(0).getFirst().getTable().equals(T1)); 097 assertTrue(report.getHoles().get(0).getFirst().isLast()); 098 assertTrue(report.getHoles().get(0).getSecond().getTable().equals(T2)); 099 assertEquals(0, report.getOverlaps().size()); 100 // Next, add overlaps to first row in t3 101 List<RegionInfo> t3Ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), T3); 102 RegionInfo ri = t3Ris.get(0); 103 RegionInfo newRi1 = RegionInfoBuilder.newBuilder(ri.getTable()). 104 setStartKey(incrementRow(ri.getStartKey())). 105 setEndKey(incrementRow(ri.getEndKey())).build(); 106 Put p1 = MetaTableAccessor.makePutFromRegionInfo(newRi1, System.currentTimeMillis()); 107 RegionInfo newRi2 = RegionInfoBuilder.newBuilder(newRi1.getTable()). 108 setStartKey(incrementRow(newRi1.getStartKey())). 109 setEndKey(incrementRow(newRi1.getEndKey())).build(); 110 Put p2 = MetaTableAccessor.makePutFromRegionInfo(newRi2, System.currentTimeMillis()); 111 MetaTableAccessor.putsToMetaTable(TEST_UTIL.getConnection(), Arrays.asList(p1, p2)); 112 gc = janitor.scan(); 113 report = janitor.getLastReport(); 114 assertFalse(report.isEmpty()); 115 // We added two overlaps so total three. 116 assertEquals(3, report.getOverlaps().size()); 117 // Assert hole is still there. 118 assertEquals(1, report.getHoles().size()); 119 // Assert other attributes are empty still. 120 assertTrue(report.getEmptyRegionInfo().isEmpty()); 121 assertTrue(report.getUnknownServers().isEmpty()); 122 // Now make bad server in t1. 123 List<RegionInfo> t1Ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), T1); 124 RegionInfo t1Ri1 = t1Ris.get(1); 125 Put pServer = new Put(t1Ri1.getRegionName()); 126 pServer.addColumn(MetaTableAccessor.getCatalogFamily(), 127 MetaTableAccessor.getServerColumn(0), Bytes.toBytes("bad.server.example.org:1234")); 128 MetaTableAccessor.putsToMetaTable(TEST_UTIL.getConnection(), Arrays.asList(pServer)); 129 gc = janitor.scan(); 130 report = janitor.getLastReport(); 131 assertFalse(report.isEmpty()); 132 // Finally, make an empty regioninfo in t1. 133 RegionInfo t1Ri2 = t1Ris.get(2); 134 Put pEmptyRI = new Put(t1Ri2.getRegionName()); 135 pEmptyRI.addColumn(MetaTableAccessor.getCatalogFamily(), 136 MetaTableAccessor.getRegionInfoColumn(), HConstants.EMPTY_BYTE_ARRAY); 137 MetaTableAccessor.putsToMetaTable(TEST_UTIL.getConnection(), Arrays.asList(pEmptyRI)); 138 gc = janitor.scan(); 139 report = janitor.getLastReport(); 140 assertEquals(1, report.getEmptyRegionInfo().size()); 141 } 142 143 /** 144 * Take last byte and add one to it. 145 */ 146 private static byte [] incrementRow(byte [] row) { 147 if (row.length == 0) { 148 return new byte []{'0'}; 149 } 150 row[row.length - 1] = (byte)(((int)row[row.length - 1]) + 1); 151 return row; 152 } 153}