hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jxi...@apache.org
Subject svn commit: r1507501 - in /hbase/branches/0.95: hbase-client/src/main/java/org/apache/hadoop/hbase/client/ hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/ hbase-server/src/main/java/org/apache/hadoop/hbase/master/ hbase-server/src/main/j...
Date Fri, 26 Jul 2013 22:52:12 GMT
Author: jxiang
Date: Fri Jul 26 22:52:12 2013
New Revision: 1507501

URL: http://svn.apache.org/r1507501
Log:
HBASE-9044 Merging regions throws NPE

Added:
    hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java
  (with props)
Modified:
    hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
    hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
    hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DispatchMergingRegionHandler.java
    hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionMergeTransactionOnCluster.java

Modified: hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java?rev=1507501&r1=1507500&r2=1507501&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
(original)
+++ hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
Fri Jul 26 22:52:12 2013
@@ -52,6 +52,7 @@ import org.apache.hadoop.hbase.exception
 import org.apache.hadoop.hbase.exceptions.FailedLogCloseException;
 import org.apache.hadoop.hbase.exceptions.HBaseSnapshotException;
 import org.apache.hadoop.hbase.exceptions.MasterNotRunningException;
+import org.apache.hadoop.hbase.exceptions.MergeRegionException;
 import org.apache.hadoop.hbase.exceptions.NotServingRegionException;
 import org.apache.hadoop.hbase.exceptions.RegionException;
 import org.apache.hadoop.hbase.exceptions.RestoreSnapshotException;
@@ -1710,6 +1711,9 @@ public class HBaseAdmin implements Abort
       if (ioe instanceof UnknownRegionException) {
         throw (UnknownRegionException) ioe;
       }
+      if (ioe instanceof MergeRegionException) {
+        throw (MergeRegionException) ioe;
+      }
       LOG.error("Unexpected exception: " + se
           + " from calling HMaster.dispatchMergingRegions");
     } catch (DeserializationException de) {
@@ -2740,4 +2744,4 @@ public class HBaseAdmin implements Abort
   public CoprocessorRpcChannel coprocessorService() {
     return new MasterCoprocessorRpcChannel(connection);
   }
-}
\ No newline at end of file
+}

Added: hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java?rev=1507501&view=auto
==============================================================================
--- hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java
(added)
+++ hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java
Fri Jul 26 22:52:12 2013
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.exceptions;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * Thrown when something is wrong in trying to merge two regions.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Stable
+public class MergeRegionException extends RegionException {
+
+  private static final long serialVersionUID = 4970899110066124122L;
+
+  /** default constructor */
+  public MergeRegionException() {
+    super();
+  }
+
+  /**
+   * Constructor
+   * @param s message
+   */
+  public MergeRegionException(String s) {
+    super(s);
+  }
+}

Propchange: hbase/branches/0.95/hbase-client/src/main/java/org/apache/hadoop/hbase/exceptions/MergeRegionException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1507501&r1=1507500&r2=1507501&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
(original)
+++ hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
Fri Jul 26 22:52:12 2013
@@ -69,6 +69,7 @@ import org.apache.hadoop.hbase.client.Re
 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
 import org.apache.hadoop.hbase.exceptions.DeserializationException;
 import org.apache.hadoop.hbase.exceptions.MasterNotRunningException;
+import org.apache.hadoop.hbase.exceptions.MergeRegionException;
 import org.apache.hadoop.hbase.exceptions.PleaseHoldException;
 import org.apache.hadoop.hbase.exceptions.TableNotDisabledException;
 import org.apache.hadoop.hbase.exceptions.TableNotFoundException;
@@ -76,9 +77,9 @@ import org.apache.hadoop.hbase.exception
 import org.apache.hadoop.hbase.exceptions.UnknownRegionException;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.executor.ExecutorType;
-import org.apache.hadoop.hbase.ipc.RpcServerInterface;
 import org.apache.hadoop.hbase.ipc.RpcServer;
 import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface;
+import org.apache.hadoop.hbase.ipc.RpcServerInterface;
 import org.apache.hadoop.hbase.ipc.ServerRpcController;
 import org.apache.hadoop.hbase.master.balancer.BalancerChore;
 import org.apache.hadoop.hbase.master.balancer.ClusterStatusChore;
@@ -1519,16 +1520,28 @@ MasterServices, Server {
               : encodedNameOfRegionB)));
     }
 
-    if (!forcible && !HRegionInfo.areAdjacent(regionStateA.getRegion(),
-            regionStateB.getRegion())) {
-      throw new ServiceException("Unable to merge not adjacent regions "
-          + regionStateA.getRegion().getRegionNameAsString() + ", "
-          + regionStateB.getRegion().getRegionNameAsString()
-          + " where forcible = " + forcible);
+    if (!regionStateA.isOpened() || !regionStateB.isOpened()) {
+      throw new ServiceException(new MergeRegionException(
+        "Unable to merge regions not online " + regionStateA + ", " + regionStateB));
+    }
+
+    HRegionInfo regionInfoA = regionStateA.getRegion();
+    HRegionInfo regionInfoB = regionStateB.getRegion();
+    if (regionInfoA.compareTo(regionInfoB) == 0) {
+      throw new ServiceException(new MergeRegionException(
+        "Unable to merge a region to itself " + regionInfoA + ", " + regionInfoB));
+    }
+
+    if (!forcible && !HRegionInfo.areAdjacent(regionInfoA, regionInfoB)) {
+      throw new ServiceException(new MergeRegionException(
+        "Unable to merge not adjacent regions "
+          + regionInfoA.getRegionNameAsString() + ", "
+          + regionInfoB.getRegionNameAsString()
+          + " where forcible = " + forcible));
     }
 
     try {
-      dispatchMergingRegions(regionStateA.getRegion(), regionStateB.getRegion(), forcible);
+      dispatchMergingRegions(regionInfoA, regionInfoB, forcible);
     } catch (IOException ioe) {
       throw new ServiceException(ioe);
     }

Modified: hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DispatchMergingRegionHandler.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DispatchMergingRegionHandler.java?rev=1507501&r1=1507500&r2=1507501&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DispatchMergingRegionHandler.java
(original)
+++ hbase/branches/0.95/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DispatchMergingRegionHandler.java
Fri Jul 26 22:52:12 2013
@@ -20,12 +20,14 @@ package org.apache.hadoop.hbase.master.h
 
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.RegionLoad;
+import org.apache.hadoop.hbase.ServerLoad;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.exceptions.RegionOpeningException;
 import org.apache.hadoop.hbase.executor.EventHandler;
@@ -34,6 +36,7 @@ import org.apache.hadoop.hbase.master.Ca
 import org.apache.hadoop.hbase.master.MasterServices;
 import org.apache.hadoop.hbase.master.RegionPlan;
 import org.apache.hadoop.hbase.master.RegionStates;
+import org.apache.hadoop.hbase.master.ServerManager;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 
 /**
@@ -98,12 +101,8 @@ public class DispatchMergingRegionHandle
       // Move region_b to region a's location, switch region_a and region_b if
       // region_a's load lower than region_b's, so we will always move lower
       // load region
-      RegionLoad loadOfRegionA = masterServices.getServerManager()
-          .getLoad(region_a_location).getRegionsLoad()
-          .get(region_a.getRegionName());
-      RegionLoad loadOfRegionB = masterServices.getServerManager()
-          .getLoad(region_b_location).getRegionsLoad()
-          .get(region_b.getRegionName());
+      RegionLoad loadOfRegionA = getRegionLoad(region_a_location, region_a);
+      RegionLoad loadOfRegionB = getRegionLoad(region_b_location, region_b);
       if (loadOfRegionA != null && loadOfRegionB != null
           && loadOfRegionA.getRequestsCount() < loadOfRegionB
               .getRequestsCount()) {
@@ -174,4 +173,16 @@ public class DispatchMergingRegionHandle
           + (EnvironmentEdgeManager.currentTimeMillis() - startTime) + "ms");
     }
   }
+
+  private RegionLoad getRegionLoad(ServerName sn, HRegionInfo hri) {
+    ServerManager serverManager =  masterServices.getServerManager();
+    ServerLoad load = serverManager.getLoad(sn);
+    if (load != null) {
+      Map<byte[], RegionLoad> regionsLoad = load.getRegionsLoad();
+      if (regionsLoad != null) {
+        return regionsLoad.get(hri.getRegionName());
+      }
+    }
+    return null;
+  }
 }
\ No newline at end of file

Modified: hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionMergeTransactionOnCluster.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionMergeTransactionOnCluster.java?rev=1507501&r1=1507500&r2=1507501&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionMergeTransactionOnCluster.java
(original)
+++ hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionMergeTransactionOnCluster.java
Fri Jul 26 22:52:12 2013
@@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.regionse
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.List;
@@ -43,7 +44,10 @@ import org.apache.hadoop.hbase.client.Pu
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.ResultScanner;
 import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.exceptions.MergeRegionException;
+import org.apache.hadoop.hbase.exceptions.UnknownRegionException;
 import org.apache.hadoop.hbase.master.HMaster;
+import org.apache.hadoop.hbase.master.RegionStates;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.Pair;
 import org.junit.AfterClass;
@@ -190,6 +194,58 @@ public class TestRegionMergeTransactionO
     }
   }
 
+  /**
+   * This test tests 1, merging region not online;
+   * 2, merging same two regions; 3, merging unknown regions.
+   * They are in one test case so that we don't have to create
+   * many tables, and these tests are simple.
+   */
+  @Test
+  public void testMerge() throws Exception {
+    LOG.info("Starting testMerge");
+    final byte[] tableName = Bytes.toBytes("testMerge");
+
+    try {
+      // Create table and load data.
+      HTable table = createTableAndLoadData(master, tableName);
+      RegionStates regionStates = master.getAssignmentManager().getRegionStates();
+      List<HRegionInfo> regions = regionStates.getRegionsOfTable(tableName);
+      // Fake offline one region
+      HRegionInfo a = regions.get(0);
+      HRegionInfo b = regions.get(1);
+      regionStates.regionOffline(a);
+      try {
+        // Merge offline region. Region a is offline here
+        admin.mergeRegions(a.getEncodedNameAsBytes(), b.getEncodedNameAsBytes(), false);
+        fail("Offline regions should not be able to merge");
+      } catch (IOException ie) {
+        assertTrue("Exception should mention regions not online",
+          ie.getMessage().contains("regions not online")
+            && ie instanceof MergeRegionException);
+      }
+      try {
+        // Merge the same region: b and b.
+        admin.mergeRegions(b.getEncodedNameAsBytes(), b.getEncodedNameAsBytes(), true);
+        fail("A region should not be able to merge with itself, even forcifully");
+      } catch (IOException ie) {
+        assertTrue("Exception should mention regions not online",
+          ie.getMessage().contains("region to itself")
+            && ie instanceof MergeRegionException);
+      }
+      try {
+        // Merge unknown regions
+        admin.mergeRegions(Bytes.toBytes("-f1"), Bytes.toBytes("-f2"), true);
+        fail("Unknown region could not be merged");
+      } catch (IOException ie) {
+        assertTrue("UnknownRegionException should be thrown",
+          ie instanceof UnknownRegionException);
+      }
+      table.close();
+    } finally {
+      TEST_UTIL.deleteTable(tableName);
+    }
+  }
+
   private void mergeRegionsAndVerifyRegionNum(HMaster master, byte[] tablename,
       int regionAnum, int regionBnum, int expectedRegionNum) throws Exception {
     requestMergeRegion(master, tablename, regionAnum, regionBnum);



Mime
View raw message