You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ra...@apache.org on 2012/05/18 19:50:32 UTC

svn commit: r1340187 - in /hbase/trunk/src: main/java/org/apache/hadoop/hbase/master/AssignmentManager.java test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java

Author: ramkrishna
Date: Fri May 18 17:50:32 2012
New Revision: 1340187

URL: http://svn.apache.org/viewvc?rev=1340187&view=rev
Log:
HBASE-5546 Master assigns region in the original region server when opening region failed (Ashutosh)

Modified:
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
    hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java?rev=1340187&r1=1340186&r2=1340187&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java Fri May 18 17:50:32 2012
@@ -857,6 +857,9 @@ public class AssignmentManager extends Z
           }
           // Handle this the same as if it were opened and then closed.
           regionState.update(RegionState.State.CLOSED, createTime, sn);
+          // When there are more than one region server a new RS is selected as the 
+          // destination and the same is updated in the regionplan. (HBASE-5546)
+          getRegionPlan(regionState, sn, true);
           this.executorService.submit(new ClosedRegionHandler(master,
             this, regionState.getRegion()));
           break;

Modified: hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java?rev=1340187&r1=1340186&r2=1340187&view=diff
==============================================================================
--- hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java (original)
+++ hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestAssignmentManager.java Fri May 18 17:50:32 2012
@@ -50,6 +50,8 @@ import org.apache.hadoop.hbase.client.Re
 import org.apache.hadoop.hbase.executor.EventHandler.EventType;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.executor.ExecutorService.ExecutorType;
+import org.apache.hadoop.hbase.master.AssignmentManager.RegionState;
+import org.apache.hadoop.hbase.master.AssignmentManager.RegionState.State;
 import org.apache.hadoop.hbase.master.handler.ServerShutdownHandler;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
@@ -98,6 +100,7 @@ public class TestAssignmentManager {
   private Server server;
   private ServerManager serverManager;
   private ZooKeeperWatcher watcher;
+  private LoadBalancer balancer;
 
   @BeforeClass
   public static void beforeClass() throws Exception {
@@ -604,6 +607,74 @@ public class TestAssignmentManager {
       assertEquals("Aborted", e.getLocalizedMessage());
     }
   }
+  /**
+   * TestCase verifies that the regionPlan is updated whenever a region fails to open 
+   * and the master tries to process RS_ZK_FAILED_OPEN state.(HBASE-5546).
+   */
+  @Test
+  public void testRegionPlanIsUpdatedWhenRegionFailsToOpen() throws IOException, KeeperException,
+      ServiceException, InterruptedException {
+    this.server.getConfiguration().setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
+        MockedLoadBalancer.class, LoadBalancer.class);
+    AssignmentManagerWithExtrasForTesting am = setUpMockedAssignmentManager(this.server,
+        this.serverManager);
+    // Boolean variable used for waiting until randomAssignment is called and new
+    // plan is generated.
+    AtomicBoolean gate = new AtomicBoolean(false);
+    if (balancer instanceof MockedLoadBalancer) {
+      ((MockedLoadBalancer) balancer).setGateVariable(gate);
+    }
+    ZKAssign.createNodeOffline(this.watcher, REGIONINFO, SERVERNAME_A);
+    int v = ZKAssign.getVersion(this.watcher, REGIONINFO);
+    ZKAssign.transitionNode(this.watcher, REGIONINFO, SERVERNAME_A, EventType.M_ZK_REGION_OFFLINE,
+        EventType.RS_ZK_REGION_FAILED_OPEN, v);
+    String path = ZKAssign.getNodeName(this.watcher, REGIONINFO.getEncodedName());
+    RegionState state = new RegionState(REGIONINFO, State.OPENING, System.currentTimeMillis(),
+        SERVERNAME_A);
+    am.regionsInTransition.put(REGIONINFO.getEncodedName(), state);
+    // a dummy plan inserted into the regionPlans. This plan is cleared and new one is formed
+    am.regionPlans.put(REGIONINFO.getEncodedName(), new RegionPlan(REGIONINFO, null, SERVERNAME_A));
+    RegionPlan regionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
+    List<ServerName> serverList = new ArrayList<ServerName>(2);
+    serverList.add(SERVERNAME_B);
+    Mockito.when(this.serverManager.createDestinationServersList(SERVERNAME_A)).thenReturn(serverList);
+    am.nodeDataChanged(path);
+    // here we are waiting until the random assignment in the load balancer is called.
+    while (!gate.get()) {
+      Thread.sleep(10);
+    }
+    // new region plan may take some time to get updated after random assignment is called and 
+    // gate is set to true.
+    RegionPlan newRegionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
+    while (newRegionPlan == null) {
+      Thread.sleep(10);
+      newRegionPlan = am.regionPlans.get(REGIONINFO.getEncodedName());
+    }
+    // the new region plan created may contain the same RS as destination but it should
+    // be new plan.
+    assertNotSame("Same region plan should not come", regionPlan, newRegionPlan);
+    assertTrue("Destnation servers should be different.", !(regionPlan.getDestination().equals(
+        newRegionPlan.getDestination())));
+  }
+  
+  /**
+   * Mocked load balancer class used in the testcase to make sure that the testcase waits until
+   * random assignment is called and the gate variable is set to true.
+   */
+  public static class MockedLoadBalancer extends DefaultLoadBalancer {
+    private AtomicBoolean gate;
+
+    public void setGateVariable(AtomicBoolean gate) {
+      this.gate = gate;
+    }
+
+    @Override
+    public ServerName randomAssignment(HRegionInfo regionInfo, List<ServerName> servers) {
+      ServerName randomServerName = super.randomAssignment(regionInfo, servers);
+      this.gate.set(true);
+      return randomServerName;
+    }
+  }
   
   /**
    * Creates a new ephemeral node in the SPLITTING state for the specified region.
@@ -696,10 +767,9 @@ public class TestAssignmentManager {
     Mockito.when(ct.getConnection()).thenReturn(connection);
     // Create and startup an executor. Used by AM handling zk callbacks.
     ExecutorService executor = startupMasterExecutor("mockedAMExecutor");
-    LoadBalancer balancer = LoadBalancerFactory.getLoadBalancer(server
-        .getConfiguration());
+    this.balancer = LoadBalancerFactory.getLoadBalancer(server.getConfiguration());
     AssignmentManagerWithExtrasForTesting am = new AssignmentManagerWithExtrasForTesting(
-        server, manager, ct, balancer, executor);
+        server, manager, ct, this.balancer, executor);
     return am;
   }