You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2019/11/26 18:11:10 UTC

[hbase] branch master updated: HBASE-23117: Bad enum in hbase:meta info:state column can fail loadMeta and stop startup (#867)

This is an automated email from the ASF dual-hosted git repository.

stack pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/master by this push:
     new 0d7a6b9  HBASE-23117: Bad enum in hbase:meta info:state column can fail loadMeta and stop startup (#867)
0d7a6b9 is described below

commit 0d7a6b9725154d5b3285c9ae38f62309db5db80b
Author: Sandeep Pal <50...@users.noreply.github.com>
AuthorDate: Tue Nov 26 10:10:01 2019 -0800

    HBASE-23117: Bad enum in hbase:meta info:state column can fail loadMeta and stop startup (#867)
    
    * Handling the BAD value in info:state columns in hbase:meta
    
    * Adding a unit test and region encoded name in the LOG
    
    * Adding a null check for region state to complete the test scenario and fixing the nit
    
    Signed-off-by: Wellington Chevreuil <wc...@apache.org>
    Signed-off-by: GuangxuCheng  <gu...@gmail.com>
    Signed-off-by: stack <st...@apache.org>
---
 .../hbase/master/assignment/RegionStateStore.java  | 17 +++++++---
 .../apache/hadoop/hbase/HBaseTestingUtility.java   |  2 +-
 .../master/assignment/TestRegionStateStore.java    | 39 ++++++++++++++++++++++
 3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
index 69bc8f7..2dbd4e6 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
@@ -132,7 +132,7 @@ public class RegionStateStore {
       if (regionInfo == null) continue;
 
       final int replicaId = regionInfo.getReplicaId();
-      final State state = getRegionState(result, replicaId);
+      final State state = getRegionState(result, replicaId, regionInfo);
 
       final ServerName lastHost = hrl.getServerName();
       final ServerName regionLocation = getRegionServer(result, replicaId);
@@ -347,13 +347,22 @@ public class RegionStateStore {
    * @return the region state, or null if unknown.
    */
   @VisibleForTesting
-  public static State getRegionState(final Result r, int replicaId) {
+  public static State getRegionState(final Result r, int replicaId, RegionInfo regionInfo) {
     Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY, getStateColumn(replicaId));
     if (cell == null || cell.getValueLength() == 0) {
       return null;
     }
-    return State.valueOf(Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
-        cell.getValueLength()));
+
+    String state = Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
+        cell.getValueLength());
+    try {
+      return State.valueOf(state);
+    } catch (IllegalArgumentException e) {
+      LOG.warn("BAD value {} in hbase:meta info:state column for region {} , " +
+              "Consider using HBCK2 setRegionState ENCODED_REGION_NAME STATE",
+          state, regionInfo.getEncodedName());
+      return null;
+    }
   }
 
   private static byte[] getStateColumn(int replicaId) {
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
index a50ac11..29bddb0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
@@ -3606,7 +3606,7 @@ public class HBaseTestingUtility extends HBaseZKTestingUtility {
                     }
                   }
                   if (RegionStateStore.getRegionState(r,
-                    info.getReplicaId()) != RegionState.State.OPEN) {
+                    info.getReplicaId(), info) != RegionState.State.OPEN) {
                     return false;
                   }
                 }
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStateStore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStateStore.java
index b4af370..c817b89 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStateStore.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionStateStore.java
@@ -19,20 +19,26 @@ package org.apache.hadoop.hbase.master.assignment;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.hadoop.hbase.HBaseClassTestRule;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.RegionInfo;
 import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.master.RegionState;
 import org.apache.hadoop.hbase.regionserver.HRegion;
 import org.apache.hadoop.hbase.testclassification.MasterTests;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -85,6 +91,39 @@ public class TestRegionStateStore {
   }
 
   @Test
+  public void testVisitMetaForBadRegionState() throws Exception {
+    final TableName tableName = TableName.valueOf("testVisitMetaForBadRegionState");
+    util.createTable(tableName, "cf");
+    final List<HRegion> regions = util.getHBaseCluster().getRegions(tableName);
+    final String encodedName = regions.get(0).getRegionInfo().getEncodedName();
+    final RegionStateStore regionStateStore = util.getHBaseCluster().getMaster().
+        getAssignmentManager().getRegionStateStore();
+
+    // add the BAD_STATE which does not exist in enum RegionState.State
+    Put put = new Put(regions.get(0).getRegionInfo().getRegionName(),
+        EnvironmentEdgeManager.currentTime());
+    put.addColumn(HConstants.CATALOG_FAMILY, HConstants.STATE_QUALIFIER,
+        Bytes.toBytes("BAD_STATE"));
+
+    try (Table table = util.getConnection().getTable(TableName.META_TABLE_NAME)) {
+      table.put(put);
+    }
+
+    final AtomicBoolean visitorCalled = new AtomicBoolean(false);
+    regionStateStore.visitMetaForRegion(encodedName, new RegionStateStore.RegionStateVisitor() {
+      @Override
+      public void visitRegionState(Result result, RegionInfo regionInfo,
+                                   RegionState.State state, ServerName regionLocation,
+                                   ServerName lastHost, long openSeqNum) {
+        assertEquals(encodedName, regionInfo.getEncodedName());
+        assertNull(state);
+        visitorCalled.set(true);
+      }
+    });
+    assertTrue("Visitor has not been called.", visitorCalled.get());
+  }
+
+  @Test
   public void testVisitMetaForRegionNonExistingRegion() throws Exception {
     final String encodedName = "fakeencodedregionname";
     final RegionStateStore regionStateStore = util.getHBaseCluster().getMaster().