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.assignment;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertNotNull;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertTrue;
025
026import java.io.IOException;
027import java.util.List;
028import java.util.concurrent.atomic.AtomicBoolean;
029import org.apache.hadoop.hbase.Cell;
030import org.apache.hadoop.hbase.HBaseClassTestRule;
031import org.apache.hadoop.hbase.HBaseTestingUtility;
032import org.apache.hadoop.hbase.HConstants;
033import org.apache.hadoop.hbase.MetaTableAccessor;
034import org.apache.hadoop.hbase.ServerName;
035import org.apache.hadoop.hbase.TableName;
036import org.apache.hadoop.hbase.TableNameTestRule;
037import org.apache.hadoop.hbase.client.Get;
038import org.apache.hadoop.hbase.client.Put;
039import org.apache.hadoop.hbase.client.RegionInfo;
040import org.apache.hadoop.hbase.client.RegionInfoBuilder;
041import org.apache.hadoop.hbase.client.Result;
042import org.apache.hadoop.hbase.client.Table;
043import org.apache.hadoop.hbase.master.RegionState;
044import org.apache.hadoop.hbase.regionserver.HRegion;
045import org.apache.hadoop.hbase.testclassification.MasterTests;
046import org.apache.hadoop.hbase.testclassification.MediumTests;
047import org.apache.hadoop.hbase.util.Bytes;
048import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
049import org.junit.AfterClass;
050import org.junit.BeforeClass;
051import org.junit.ClassRule;
052import org.junit.Rule;
053import org.junit.Test;
054import org.junit.experimental.categories.Category;
055
056import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
057
058@Category({ MasterTests.class, MediumTests.class })
059public class TestRegionStateStore {
060
061  @ClassRule
062  public static final HBaseClassTestRule CLASS_RULE =
063    HBaseClassTestRule.forClass(TestRegionStateStore.class);
064
065  private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
066
067  @Rule
068  public final TableNameTestRule name = new TableNameTestRule();
069
070  @BeforeClass
071  public static void beforeClass() throws Exception {
072    UTIL.startMiniCluster();
073  }
074
075  @AfterClass
076  public static void tearDown() throws Exception {
077    UTIL.shutdownMiniCluster();
078  }
079
080  @Test
081  public void testVisitMetaForRegionExistingRegion() throws Exception {
082    final TableName tableName = name.getTableName();
083    UTIL.createTable(tableName, "cf");
084    final List<HRegion> regions = UTIL.getHBaseCluster().getRegions(tableName);
085    final String encodedName = regions.get(0).getRegionInfo().getEncodedName();
086    final RegionStateStore regionStateStore =
087      UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStateStore();
088    final AtomicBoolean visitorCalled = new AtomicBoolean(false);
089    regionStateStore.visitMetaForRegion(encodedName, new RegionStateStore.RegionStateVisitor() {
090      @Override
091      public void visitRegionState(Result result, RegionInfo regionInfo, RegionState.State state,
092        ServerName regionLocation, ServerName lastHost, long openSeqNum) {
093        assertEquals(encodedName, regionInfo.getEncodedName());
094        visitorCalled.set(true);
095      }
096    });
097    assertTrue("Visitor has not been called.", visitorCalled.get());
098  }
099
100  @Test
101  public void testVisitMetaForBadRegionState() throws Exception {
102    final TableName tableName = name.getTableName();
103    UTIL.createTable(tableName, "cf");
104    final List<HRegion> regions = UTIL.getHBaseCluster().getRegions(tableName);
105    final String encodedName = regions.get(0).getRegionInfo().getEncodedName();
106    final RegionStateStore regionStateStore =
107      UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStateStore();
108
109    // add the BAD_STATE which does not exist in enum RegionState.State
110    Put put =
111      new Put(regions.get(0).getRegionInfo().getRegionName(), EnvironmentEdgeManager.currentTime());
112    put.addColumn(HConstants.CATALOG_FAMILY, HConstants.STATE_QUALIFIER,
113      Bytes.toBytes("BAD_STATE"));
114
115    try (Table table = UTIL.getConnection().getTable(TableName.META_TABLE_NAME)) {
116      table.put(put);
117    }
118
119    final AtomicBoolean visitorCalled = new AtomicBoolean(false);
120    regionStateStore.visitMetaForRegion(encodedName, new RegionStateStore.RegionStateVisitor() {
121      @Override
122      public void visitRegionState(Result result, RegionInfo regionInfo, RegionState.State state,
123        ServerName regionLocation, ServerName lastHost, long openSeqNum) {
124        assertEquals(encodedName, regionInfo.getEncodedName());
125        assertNull(state);
126        visitorCalled.set(true);
127      }
128    });
129    assertTrue("Visitor has not been called.", visitorCalled.get());
130  }
131
132  @Test
133  public void testVisitMetaForRegionNonExistingRegion() throws Exception {
134    final String encodedName = "fakeencodedregionname";
135    final RegionStateStore regionStateStore =
136      UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStateStore();
137    final AtomicBoolean visitorCalled = new AtomicBoolean(false);
138    regionStateStore.visitMetaForRegion(encodedName, new RegionStateStore.RegionStateVisitor() {
139      @Override
140      public void visitRegionState(Result result, RegionInfo regionInfo, RegionState.State state,
141        ServerName regionLocation, ServerName lastHost, long openSeqNum) {
142        visitorCalled.set(true);
143      }
144    });
145    assertFalse("Visitor has been called, but it shouldn't.", visitorCalled.get());
146  }
147
148  @Test
149  public void testMetaLocationForRegionReplicasIsRemovedAtTableDeletion() throws IOException {
150    long regionId = EnvironmentEdgeManager.currentTime();
151    TableName tableName = name.getTableName();
152    RegionInfo primary = RegionInfoBuilder.newBuilder(tableName)
153      .setStartKey(HConstants.EMPTY_START_ROW).setEndKey(HConstants.EMPTY_END_ROW).setSplit(false)
154      .setRegionId(regionId).setReplicaId(0).build();
155
156    try (Table meta = MetaTableAccessor.getMetaHTable(UTIL.getConnection())) {
157      List<RegionInfo> regionInfos = Lists.newArrayList(primary);
158      MetaTableAccessor.addRegionsToMeta(UTIL.getConnection(), regionInfos, 3);
159      final RegionStateStore regionStateStore =
160        UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStateStore();
161      regionStateStore.removeRegionReplicas(tableName, 3, 1);
162      Get get = new Get(primary.getRegionName());
163      Result result = meta.get(get);
164      for (int replicaId = 0; replicaId < 3; replicaId++) {
165        Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
166          MetaTableAccessor.getServerColumn(replicaId));
167        Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
168          MetaTableAccessor.getStartCodeColumn(replicaId));
169        Cell stateCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
170          MetaTableAccessor.getRegionStateColumn(replicaId));
171        Cell snCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
172          MetaTableAccessor.getServerNameColumn(replicaId));
173        if (replicaId == 0) {
174          assertNotNull(stateCell);
175        } else {
176          assertNull(serverCell);
177          assertNull(startCodeCell);
178          assertNull(stateCell);
179          assertNull(snCell);
180        }
181      }
182    }
183  }
184}