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 java.io.IOException; 021import java.util.List; 022 023import org.apache.hadoop.hbase.HBaseClassTestRule; 024import org.apache.hadoop.hbase.HBaseTestingUtility; 025import org.apache.hadoop.hbase.HConstants; 026import org.apache.hadoop.hbase.MetaTableAccessor; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.client.RegionInfo; 029import org.apache.hadoop.hbase.testclassification.LargeTests; 030import org.apache.hadoop.hbase.testclassification.MasterTests; 031import org.junit.AfterClass; 032import org.junit.Assert; 033import org.junit.BeforeClass; 034import org.junit.ClassRule; 035import org.junit.Rule; 036import org.junit.Test; 037import org.junit.experimental.categories.Category; 038import org.junit.rules.TestName; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043@Category({MasterTests.class, LargeTests.class}) 044public class TestMetaFixer { 045 @ClassRule 046 public static final HBaseClassTestRule CLASS_RULE = 047 HBaseClassTestRule.forClass(TestMetaFixer.class); 048 @Rule 049 public TestName name = new TestName(); 050 private static final Logger LOG = LoggerFactory.getLogger(TestMetaFixer.class); 051 052 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 053 054 @BeforeClass 055 public static void setupBeforeClass() throws Exception { 056 TEST_UTIL.startMiniCluster(); 057 } 058 059 @AfterClass 060 public static void tearDownAfterClass() throws Exception { 061 TEST_UTIL.shutdownMiniCluster(); 062 } 063 064 private void deleteRegion(MasterServices services, RegionInfo ri) throws IOException { 065 MetaTableAccessor.deleteRegionInfo(TEST_UTIL.getConnection(), ri); 066 // Delete it from Master context too else it sticks around. 067 services.getAssignmentManager().getRegionStates().deleteRegion(ri); 068 } 069 070 @Test 071 public void testPlugsHoles() throws IOException { 072 TableName tn = TableName.valueOf(this.name.getMethodName()); 073 TEST_UTIL.createMultiRegionTable(tn, HConstants.CATALOG_FAMILY); 074 List<RegionInfo> ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 075 MasterServices services = TEST_UTIL.getHBaseCluster().getMaster(); 076 services.getCatalogJanitor().scan(); 077 CatalogJanitor.Report report = services.getCatalogJanitor().getLastReport(); 078 Assert.assertTrue(report.isEmpty()); 079 int originalCount = ris.size(); 080 // Remove first, last and middle region. See if hole gets plugged. Table has 26 regions. 081 deleteRegion(services, ris.get(ris.size() -1)); 082 deleteRegion(services, ris.get(3)); 083 deleteRegion(services, ris.get(0)); 084 ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 085 services.getCatalogJanitor().scan(); 086 report = services.getCatalogJanitor().getLastReport(); 087 Assert.assertEquals(report.toString(), 3, report.getHoles().size()); 088 MetaFixer fixer = new MetaFixer(services); 089 Assert.assertTrue(fixer.fixHoles(report)); 090 services.getCatalogJanitor().scan(); 091 report = services.getCatalogJanitor().getLastReport(); 092 Assert.assertTrue(report.toString(), report.isEmpty()); 093 // Disable and reenable so the added regions get reassigned. 094 TEST_UTIL.getAdmin().disableTable(tn); 095 TEST_UTIL.getAdmin().enableTable(tn); 096 ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 097 Assert.assertEquals(originalCount, ris.size()); 098 } 099 100 /** 101 * Just make sure running fixMeta does right thing for the case 102 * of a single-region Table where the region gets dropped. 103 * There is nothing much we can do. We can't restore what 104 * we don't know about (at least from a read of hbase:meta). 105 */ 106 @Test 107 public void testOneRegionTable() throws IOException { 108 TableName tn = TableName.valueOf(this.name.getMethodName()); 109 TEST_UTIL.createTable(tn, HConstants.CATALOG_FAMILY); 110 List<RegionInfo> ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 111 MasterServices services = TEST_UTIL.getHBaseCluster().getMaster(); 112 services.getCatalogJanitor().scan(); 113 CatalogJanitor.Report report = services.getCatalogJanitor().getLastReport(); 114 int originalCount = ris.size(); 115 deleteRegion(services, ris.get(0)); 116 services.getCatalogJanitor().scan(); 117 report = services.getCatalogJanitor().getLastReport(); 118 ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 119 Assert.assertTrue(ris.isEmpty()); 120 MetaFixer fixer = new MetaFixer(services); 121 Assert.assertFalse(fixer.fixHoles(report)); 122 report = services.getCatalogJanitor().getLastReport(); 123 Assert.assertTrue(report.isEmpty()); 124 ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 125 Assert.assertEquals(0, ris.size()); 126 } 127}