hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From st...@apache.org
Subject svn commit: r1136345 - in /hbase/trunk: CHANGES.txt src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java src/main/java/org/apache/hadoop/hbase/master/HMaster.java src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java
Date Thu, 16 Jun 2011 09:39:06 GMT
Author: stack
Date: Thu Jun 16 09:39:05 2011
New Revision: 1136345

URL: http://svn.apache.org/viewvc?rev=1136345&view=rev
Log:
HBASE-3946 HBASE-3946 broke TestMasterFailover

Modified:
    hbase/trunk/CHANGES.txt
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
    hbase/trunk/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java

Modified: hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hbase/trunk/CHANGES.txt?rev=1136345&r1=1136344&r2=1136345&view=diff
==============================================================================
--- hbase/trunk/CHANGES.txt (original)
+++ hbase/trunk/CHANGES.txt Thu Jun 16 09:39:05 2011
@@ -126,6 +126,7 @@ Release 0.91.0 - Unreleased
    HBASE-3963  Schedule all log-spliiting at startup all at once (mingjian)
    HBASE-3983  list command in shell seems broken
    HBASE-3793  HBASE-3468 Broke checkAndPut with null value (Ming Ma)
+   HBASE-3995  HBASE-3946 broke TestMasterFailover
 
   IMPROVEMENTS
    HBASE-3290  Max Compaction Size (Nicolas Spiegelberg via Stack)  

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=1136345&r1=1136344&r2=1136345&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 Thu Jun
16 09:39:05 2011
@@ -64,8 +64,8 @@ import org.apache.hadoop.hbase.master.ha
 import org.apache.hadoop.hbase.master.handler.ServerShutdownHandler;
 import org.apache.hadoop.hbase.master.handler.SplitRegionHandler;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.hbase.util.FSUtils;
+import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.hbase.util.Threads;
 import org.apache.hadoop.hbase.util.Writables;
 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
@@ -79,7 +79,6 @@ import org.apache.zookeeper.AsyncCallbac
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.NoNodeException;
 import org.apache.zookeeper.data.Stat;
-import org.apache.hadoop.hbase.client.Get;
 
 /**
  * Manages and performs region assignment.
@@ -238,14 +237,37 @@ public class AssignmentManager extends Z
     // Returns servers who have not checked in (assumed dead) and their regions
     Map<ServerName,List<Pair<HRegionInfo,Result>>> deadServers =
       rebuildUserRegions();
-    // Process list of dead servers
+    // Process list of dead servers; note this will add regions to the RIT.
+    // processRegionsInTransition will read them and assign them out.
     processDeadServers(deadServers);
     // Check existing regions in transition
-    processRegionsInTransition();
+    processRegionsInTransition(deadServers);
   }
 
+  /**
+   * Process all regions that are in transition up in zookeeper.  Used by
+   * master joining an already running cluster.
+   * @throws KeeperException
+   * @throws IOException
+   * @throws InterruptedException
+   */
   void processRegionsInTransition()
   throws KeeperException, IOException, InterruptedException {
+    // Pass null to signify no dead servers in this context.
+    processRegionsInTransition(null);
+  }
+
+  /**
+   * Process all regions that are in transition up in zookeeper.  Used by
+   * master joining an already running cluster.
+   * @param deadServers Map of dead servers and their regions.  Can be null.
+   * @throws KeeperException
+   * @throws IOException
+   * @throws InterruptedException
+   */
+  void processRegionsInTransition(
+      final Map<ServerName, List<Pair<HRegionInfo, Result>>> deadServers)
+  throws KeeperException, IOException, InterruptedException {
     List<String> nodes = ZKUtil.listChildrenAndWatchForNewChildren(watcher,
       watcher.assignmentZNode);
     // Run through all regions.  If they are not assigned and not in RIT, then
@@ -260,7 +282,7 @@ public class AssignmentManager extends Z
         break;
       }
       if (nodes.contains(e.getKey().getEncodedName())) {
-        LOG.debug("Found " + e + " in RITs");
+        LOG.debug("Found " + e.getKey().getRegionNameAsString() + " in RITs");
         // Could be a meta region.
         regionsToProcess = true;
         break;
@@ -272,7 +294,7 @@ public class AssignmentManager extends Z
       LOG.info("Found regions out on cluster or in RIT; failover");
       if (!nodes.isEmpty()) {
         for (String encodedRegionName: nodes) {
-          processRegionInTransition(encodedRegionName, null);
+          processRegionInTransition(encodedRegionName, null, deadServers);
         }
       }
     } else {
@@ -296,7 +318,8 @@ public class AssignmentManager extends Z
    */
   boolean processRegionInTransitionAndBlockUntilAssigned(final HRegionInfo hri)
   throws InterruptedException, KeeperException, IOException {
-    boolean intransistion = processRegionInTransition(hri.getEncodedName(), hri);
+    boolean intransistion =
+      processRegionInTransition(hri.getEncodedName(), hri, null);
     if (!intransistion) return intransistion;
     synchronized(this.regionsInTransition) {
       while (!this.master.isStopped() &&
@@ -308,15 +331,18 @@ public class AssignmentManager extends Z
   }
 
   /**
-   * Process failover of <code>servername</code>.  Look in RIT.
+   * Process failover of new master for region <code>encodedRegionName</code>
+   * up in zookeeper.
    * @param encodedRegionName Region to process failover for.
    * @param regionInfo If null we'll go get it from meta table.
+   * @param deadServers Can be null 
    * @return True if we processed <code>regionInfo</code> as a RIT.
    * @throws KeeperException
    * @throws IOException
    */
   boolean processRegionInTransition(final String encodedRegionName,
-      final HRegionInfo regionInfo)
+      final HRegionInfo regionInfo,
+      final Map<ServerName,List<Pair<HRegionInfo,Result>>> deadServers)
   throws KeeperException, IOException {
     RegionTransitionData data = ZKAssign.getData(watcher, encodedRegionName);
     if (data == null) return false;
@@ -327,12 +353,13 @@ public class AssignmentManager extends Z
       if (p == null) return false;
       hri = p.getFirst();
     }
-    processRegionsInTransition(data, hri);
+    processRegionsInTransition(data, hri, deadServers);
     return true;
   }
 
   void processRegionsInTransition(final RegionTransitionData data,
-      final HRegionInfo regionInfo)
+      final HRegionInfo regionInfo,
+      final Map<ServerName,List<Pair<HRegionInfo,Result>>> deadServers)
   throws KeeperException {
     String encodedRegionName = regionInfo.getEncodedName();
     LOG.info("Processing region " + regionInfo.getRegionNameAsString() +
@@ -340,30 +367,33 @@ public class AssignmentManager extends Z
     synchronized (regionsInTransition) {
       switch (data.getEventType()) {
       case RS_ZK_REGION_CLOSING:
-        // Just insert region into RIT.
-        // If this never updates the timeout will trigger new assignment
-        regionsInTransition.put(encodedRegionName, new RegionState(
+        if (isOnDeadServer(regionInfo, deadServers)) {
+          // If was on dead server, its closed now.  Force to OFFLINE and this
+          // will get it reassigned if appropriate
+          forceOffline(regionInfo, data);
+        } else {
+          // Just insert region into RIT.
+          // If this never updates the timeout will trigger new assignment
+          regionsInTransition.put(encodedRegionName, new RegionState(
             regionInfo, RegionState.State.CLOSING,
             data.getStamp(), data.getOrigin()));
+        }
         break;
 
       case RS_ZK_REGION_CLOSED:
         // Region is closed, insert into RIT and handle it
-        regionsInTransition.put(encodedRegionName, new RegionState(
-            regionInfo, RegionState.State.CLOSED,
-            data.getStamp(), data.getOrigin()));
-        new ClosedRegionHandler(master, this, regionInfo).process();
+        addToRITandCallClose(regionInfo, RegionState.State.CLOSED, data);
         break;
 
       case M_ZK_REGION_OFFLINE:
         // Region is offline, insert into RIT and handle it like a closed
-        regionsInTransition.put(encodedRegionName, new RegionState(
-            regionInfo, RegionState.State.OFFLINE,
-            data.getStamp(), data.getOrigin()));
-        new ClosedRegionHandler(master, this, regionInfo).process();
+        addToRITandCallClose(regionInfo, RegionState.State.OFFLINE, data);
         break;
 
       case RS_ZK_REGION_OPENING:
+        // TODO: Could check if it was on deadServers.  If it was, then we could
+        // do what happens in TimeoutMonitor when it sees this condition.
+
         // Just insert region into RIT
         // If this never updates the timeout will trigger new assignment
         regionsInTransition.put(encodedRegionName, new RegionState(
@@ -374,12 +404,11 @@ public class AssignmentManager extends Z
       case RS_ZK_REGION_OPENED:
         // Region is opened, insert into RIT and handle it
         regionsInTransition.put(encodedRegionName, new RegionState(
-            regionInfo, RegionState.State.OPENING,
+            regionInfo, RegionState.State.OPEN,
             data.getStamp(), data.getOrigin()));
-        ServerName sn =
-          data.getOrigin() == null? null: data.getOrigin();
-        // hsi could be null if this server is no longer online.  If
-        // that the case, just let this RIT timeout; it'll be assigned
+        ServerName sn = data.getOrigin() == null? null: data.getOrigin();
+        // sn could be null if this server is no longer online.  If
+        // that is the case, just let this RIT timeout; it'll be assigned
         // to new server then.
         if (sn == null) {
           LOG.warn("Region in transition " + regionInfo.getEncodedName() +
@@ -387,13 +416,68 @@ public class AssignmentManager extends Z
             "assigned elsewhere");
           break;
         }
-        new OpenedRegionHandler(master, this, regionInfo, sn).process();
+        if (isOnDeadServer(regionInfo, deadServers)) {
+          // If was on a dead server, then its not open any more; needs handling.
+          forceOffline(regionInfo, data);
+        } else {
+          new OpenedRegionHandler(master, this, regionInfo, sn).process();
+        }
         break;
       }
     }
   }
 
   /**
+   * Put the region <code>hri</code> into an offline state up in zk.
+   * @param hri
+   * @param oldData
+   * @throws KeeperException
+   */
+  private void forceOffline(final HRegionInfo hri,
+      final RegionTransitionData oldData)
+  throws KeeperException {
+    // If was on dead server, its closed now.  Force to OFFLINE and then
+    // handle it like a close; this will get it reassigned if appropriate
+    LOG.debug("RIT " + hri.getEncodedName() + " in state=" +
+      oldData.getEventType() + " was on deadserver; forcing offline");
+    ZKAssign.createOrForceNodeOffline(this.watcher, hri,
+      this.master.getServerName());
+    addToRITandCallClose(hri, RegionState.State.OFFLINE, oldData);
+  }
+
+  /**
+   * Add to the in-memory copy of regions in transition and then call close
+   * handler on passed region <code>hri</code>
+   * @param hri
+   * @param state
+   * @param oldData
+   */
+  private void addToRITandCallClose(final HRegionInfo hri,
+      final RegionState.State state, final RegionTransitionData oldData) {
+    this.regionsInTransition.put(hri.getEncodedName(),
+      new RegionState(hri, state, oldData.getStamp(), oldData.getOrigin()));
+    new ClosedRegionHandler(this.master, this, hri).process();
+  }
+
+  /**
+   * @param regionInfo
+   * @param deadServers Map of deadServers and the regions they were carrying;
+   * can be null.
+   * @return True if the passed regionInfo in the passed map of deadServers?
+   */
+  private boolean isOnDeadServer(final HRegionInfo regionInfo,
+      final Map<ServerName, List<Pair<HRegionInfo, Result>>> deadServers)
{
+    if (deadServers == null) return false;
+    for (Map.Entry<ServerName, List<Pair<HRegionInfo, Result>>> deadServer:
+        deadServers.entrySet()) {
+      for (Pair<HRegionInfo, Result> e: deadServer.getValue()) {
+        if (e.getFirst().equals(regionInfo)) return true;
+      }
+    }
+    return false;
+  }
+
+  /**
    * Handles various states an unassigned node can be in.
    * <p>
    * Method is called when a state change is suspected for an unassigned node.
@@ -418,7 +502,7 @@ public class AssignmentManager extends Z
       if (!serverManager.isServerOnline(sn) &&
           !this.master.getServerName().equals(sn)) {
         LOG.warn("Attempted to handle region transition for server but " +
-          "server is not online: " + data.getRegionName());
+          "server is not online: " + Bytes.toString(data.getRegionName()));
         return;
       }
       String encodedName = HRegionInfo.encodeRegionName(data.getRegionName());
@@ -1703,7 +1787,7 @@ public class AssignmentManager extends Z
       Map<ServerName, List<Pair<HRegionInfo, Result>>> deadServers)
   throws IOException, KeeperException {
     for (Map.Entry<ServerName, List<Pair<HRegionInfo,Result>>> deadServer:
-      deadServers.entrySet()) {
+        deadServers.entrySet()) {
       List<Pair<HRegionInfo,Result>> regions = deadServer.getValue();
       for (Pair<HRegionInfo,Result> region : regions) {
         HRegionInfo regionInfo = region.getFirst();
@@ -1711,12 +1795,12 @@ public class AssignmentManager extends Z
         // If region was in transition (was in zk) force it offline for reassign
         try {
           // Process with existing RS shutdown code  
-          boolean isNotDisabledAndSplitted =
+          boolean assign =
             ServerShutdownHandler.processDeadRegion(regionInfo, result, this,
             this.catalogTracker);
-          if (isNotDisabledAndSplitted) {
+          if (assign) {
             ZKAssign.createOrForceNodeOffline(watcher, regionInfo,
-              master.getServerName()); 
+              master.getServerName());
           }
         } catch (KeeperException.NoNodeException nne) {
           // This is fine

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1136345&r1=1136344&r2=1136345&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Thu Jun 16 09:39:05
2011
@@ -1195,6 +1195,8 @@ implements HMasterInterface, HMasterRegi
       // Update in-memory structures to reflect our earlier Root/Meta assignment.
       assignRootAndMeta(status);
       // process RIT if any
+      // TODO: Why does this not call AssignmentManager.joinCluster?  Otherwise
+      // we are not processing dead servers if any.
       this.assignmentManager.processRegionsInTransition();
       return true;
     } finally {

Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java?rev=1136345&r1=1136344&r2=1136345&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java Thu Jun 16 09:39:05
2011
@@ -390,9 +390,9 @@ public class ZKAssign {
       throw KeeperException.create(Code.NONODE);
     }
     RegionTransitionData data = RegionTransitionData.fromBytes(bytes);
-    if(!data.getEventType().equals(expectedState)) {
+    if (!data.getEventType().equals(expectedState)) {
       LOG.warn(zkw.prefix("Attempting to delete unassigned " +
-        "node in " + expectedState +
+        "node " + regionName + " in " + expectedState +
         " state but node is in " + data.getEventType() + " state"));
       return false;
     }



Mime
View raw message