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/29 18:18:49 UTC

svn commit: r1343817 - in /hbase/trunk/hbase-server/src: main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java

Author: ramkrishna
Date: Tue May 29 16:18:49 2012
New Revision: 1343817

URL: http://svn.apache.org/viewvc?rev=1343817&view=rev
Log:
HBASE-6088 Region splitting not happened for long time due to ZK exception while creating RS_ZK_SPLITTING node (Rajesh)

Modified:
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java?rev=1343817&r1=1343816&r2=1343817&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitTransaction.java Tue May 29 16:18:49 2012
@@ -109,6 +109,10 @@ public class SplitTransaction {
    */
   enum JournalEntry {
     /**
+     * Before creating node in splitting state.
+     */
+    STARTED_SPLITTING,
+    /**
      * Set region as in transition, set it into SPLITTING state.
      */
     SET_SPLITTING_IN_ZK,
@@ -232,7 +236,8 @@ public class SplitTransaction {
     this.fileSplitTimeout = testing ? this.fileSplitTimeout :
         server.getConfiguration().getLong("hbase.regionserver.fileSplitTimeout",
           this.fileSplitTimeout);
-
+    
+    this.journal.add(JournalEntry.STARTED_SPLITTING);
     // Set ephemeral SPLITTING znode up in zk.  Mocked servers sometimes don't
     // have zookeeper so don't do zk stuff if server or zookeeper is null
     if (server != null && server.getZooKeeper() != null) {
@@ -733,9 +738,16 @@ public class SplitTransaction {
     while (iterator.hasPrevious()) {
       JournalEntry je = iterator.previous();
       switch(je) {
+      
+      case STARTED_SPLITTING:
+        if (server != null && server.getZooKeeper() != null) {
+          cleanZK(server, this.parent.getRegionInfo(), false);
+        }
+        break;
+      
       case SET_SPLITTING_IN_ZK:
         if (server != null && server.getZooKeeper() != null) {
-          cleanZK(server, this.parent.getRegionInfo());
+          cleanZK(server, this.parent.getRegionInfo(), true);
         }
         break;
 
@@ -828,11 +840,15 @@ public class SplitTransaction {
     LOG.info("Cleaned up old failed split transaction detritus: " + splitdir);
   }
 
-  private static void cleanZK(final Server server, final HRegionInfo hri) {
+  private static void cleanZK(final Server server, final HRegionInfo hri, boolean abort) {
     try {
       // Only delete if its in expected state; could have been hijacked.
       ZKAssign.deleteNode(server.getZooKeeper(), hri.getEncodedName(),
         EventType.RS_ZK_REGION_SPLITTING);
+    } catch (KeeperException.NoNodeException nn) {
+      if (abort) {
+        server.abort("Failed cleanup of " + hri.getRegionNameAsString(), nn);
+      }      
     } catch (KeeperException e) {
       server.abort("Failed cleanup of " + hri.getRegionNameAsString(), e);
     }
@@ -852,9 +868,8 @@ public class SplitTransaction {
    * @throws KeeperException 
    * @throws IOException 
    */
-  private static int createNodeSplitting(final ZooKeeperWatcher zkw,
-      final HRegionInfo region, final ServerName serverName)
-  throws KeeperException, IOException {
+  int createNodeSplitting(final ZooKeeperWatcher zkw, final HRegionInfo region,
+      final ServerName serverName) throws KeeperException, IOException {
     LOG.debug(zkw.prefix("Creating ephemeral node for " +
       region.getEncodedName() + " in SPLITTING state"));
     RegionTransition rt = RegionTransition.createRegionTransition(EventType.RS_ZK_REGION_SPLITTING,
@@ -911,10 +926,18 @@ public class SplitTransaction {
       znodeVersion, payload);
   }
 
-  private static int transitionNodeSplitting(final ZooKeeperWatcher zkw,
-      final HRegionInfo parent,
-      final ServerName serverName, final int version)
-  throws KeeperException, IOException {
+  /**
+   * 
+   * @param zkw zk reference
+   * @param parent region to be transitioned to splitting
+   * @param serverName server event originates from
+   * @param version znode version
+   * @return version of node after transition, -1 if unsuccessful transition
+   * @throws KeeperException
+   * @throws IOException
+   */
+  int transitionNodeSplitting(final ZooKeeperWatcher zkw, final HRegionInfo parent,
+      final ServerName serverName, final int version) throws KeeperException, IOException {
     return ZKAssign.transitionNode(zkw, parent, serverName,
       EventType.RS_ZK_REGION_SPLITTING, EventType.RS_ZK_REGION_SPLITTING, version);
   }

Modified: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java?rev=1343817&r1=1343816&r2=1343817&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java (original)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSplitTransactionOnCluster.java Tue May 29 16:18:49 2012
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 import java.io.IOException;
 import java.util.List;
@@ -43,6 +44,7 @@ import org.apache.hadoop.hbase.util.JVMC
 import org.apache.hadoop.hbase.util.Threads;
 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
+import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.NodeExistsException;
 import org.apache.zookeeper.data.Stat;
@@ -520,6 +522,84 @@ public class TestSplitTransactionOnClust
     }
   }
 
+  /**
+   * 
+   * While transitioning node from RS_ZK_REGION_SPLITTING to
+   * RS_ZK_REGION_SPLITTING during region split,if zookeper went down split always
+   * fails for the region. HBASE-6088 fixes this scenario. 
+   * This test case is to test the znode is deleted(if created) or not in roll back.
+   * 
+   * @throws IOException
+   * @throws InterruptedException
+   * @throws KeeperException
+   */
+  @Test
+  public void testSplitBeforeSettingSplittingInZK() throws IOException,
+      InterruptedException, KeeperException {
+    testSplitBeforeSettingSplittingInZK(true);
+    testSplitBeforeSettingSplittingInZK(false);
+  }
+
+  private void testSplitBeforeSettingSplittingInZK(boolean nodeCreated) throws IOException,
+      KeeperException {
+    final byte[] tableName = Bytes.toBytes("testSplitBeforeSettingSplittingInZK");
+    HBaseAdmin admin = TESTING_UTIL.getHBaseAdmin();
+    try {
+      // Create table then get the single region for our new table.
+      HTableDescriptor htd = new HTableDescriptor(tableName);
+      htd.addFamily(new HColumnDescriptor("cf"));
+      admin.createTable(htd);
+
+      List<HRegion> regions = cluster.getRegions(tableName);
+      int regionServerIndex = cluster.getServerWith(regions.get(0).getRegionName());
+      HRegionServer regionServer = cluster.getRegionServer(regionServerIndex);
+      SplitTransaction st = null;
+      if (nodeCreated) {
+        st = new MockedSplitTransaction(regions.get(0), null) {
+          @Override
+          int transitionNodeSplitting(ZooKeeperWatcher zkw, HRegionInfo parent,
+              ServerName serverName, int version) throws KeeperException, IOException {
+            throw new IOException();
+          }
+        };
+      } else {
+        st = new MockedSplitTransaction(regions.get(0), null) {
+          @Override
+          int createNodeSplitting(ZooKeeperWatcher zkw, HRegionInfo region, ServerName serverName)
+              throws KeeperException, IOException {
+            throw new IOException();
+          }
+        };
+      }
+      try {
+        st.execute(regionServer, regionServer);
+      } catch (IOException e) {
+        String node = ZKAssign.getNodeName(regionServer.getZooKeeper(), regions.get(0)
+            .getRegionInfo().getEncodedName());
+        if (nodeCreated) {
+          assertFalse(ZKUtil.checkExists(regionServer.getZooKeeper(), node) == -1);
+        } else {
+          assertTrue(ZKUtil.checkExists(regionServer.getZooKeeper(), node) == -1);
+        }
+        assertTrue(st.rollback(regionServer, regionServer));
+        assertTrue(ZKUtil.checkExists(regionServer.getZooKeeper(), node) == -1);
+      }
+    } finally {
+      if (admin.isTableAvailable(tableName) && admin.isTableEnabled(tableName)) {
+        admin.disableTable(tableName);
+        admin.deleteTable(tableName);
+      }
+    }
+  }
+  
+  public static class MockedSplitTransaction extends SplitTransaction {
+
+    public MockedSplitTransaction(HRegion r, byte[] splitrow) {
+      super(r, splitrow);
+    }
+
+  }
+
   private MockMasterWithoutCatalogJanitor abortAndWaitForMaster() 
   throws IOException, InterruptedException {
     cluster.abortMaster(0);