Author: stack
Date: Tue Jun 21 20:28:56 2011
New Revision: 1138169

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

Modified:
    hbase/branches/0.90/CHANGES.txt
    
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
    
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
    
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
    
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java
    
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java

Modified: hbase/branches/0.90/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/CHANGES.txt?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- hbase/branches/0.90/CHANGES.txt (original)
+++ hbase/branches/0.90/CHANGES.txt Tue Jun 21 20:28:56 2011
@@ -40,6 +40,7 @@ Release 0.90.4 - Unreleased
    HBASE-3988  Infinite loop for secondary master (Liyin Tang)
    HBASE-3989  Error occured while RegionServer report to Master "we are up"
                should get master address again (Jieshan Bean)
+   HBASE-3995  HBASE-3946 broke TestMasterFailover
 
 
   IMPROVEMENT

Modified: 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
 (original)
+++ 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
 Tue Jun 21 20:28:56 2011
@@ -22,8 +22,6 @@ package org.apache.hadoop.hbase.master;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
-import java.io.EOFException;
-import java.net.ConnectException;
 import java.lang.Thread.UncaughtExceptionHandler;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -55,9 +53,9 @@ import org.apache.hadoop.hbase.catalog.C
 import org.apache.hadoop.hbase.catalog.MetaReader;
 import org.apache.hadoop.hbase.catalog.RootLocationEditor;
 import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.executor.EventHandler.EventType;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.executor.RegionTransitionData;
-import org.apache.hadoop.hbase.executor.EventHandler.EventType;
 import org.apache.hadoop.hbase.master.LoadBalancer.RegionPlan;
 import org.apache.hadoop.hbase.master.handler.ClosedRegionHandler;
 import org.apache.hadoop.hbase.master.handler.OpenedRegionHandler;
@@ -68,9 +66,9 @@ import org.apache.hadoop.hbase.util.Thre
 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
 import org.apache.hadoop.hbase.zookeeper.ZKTable;
 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
+import org.apache.hadoop.hbase.zookeeper.ZKUtil.NodeAndData;
 import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener;
 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
-import org.apache.hadoop.hbase.zookeeper.ZKUtil.NodeAndData;
 import org.apache.hadoop.io.Writable;
 import org.apache.hadoop.ipc.RemoteException;
 import org.apache.zookeeper.AsyncCallback;
@@ -217,11 +215,39 @@ public class AssignmentManager extends Z
 
     // Scan META to build list of existing regions, servers, and assignment
     // Returns servers who have not checked in (assumed dead) and their regions
-    Map<HServerInfo,List<Pair<HRegionInfo,Result>>> deadServers =
+    Map<String, 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(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<String, List<Pair<HRegionInfo, Result>>> deadServers)
+  throws KeeperException, IOException, InterruptedException {
     List<String> nodes = ZKUtil.listChildrenAndWatchForNewChildren(watcher,
         watcher.assignmentZNode);
     if (nodes.isEmpty()) {
@@ -231,7 +257,7 @@ public class AssignmentManager extends Z
     LOG.info("Failed-over master needs to process " + nodes.size() +
         " regions in transition");
     for (String encodedRegionName: nodes) {
-      processRegionInTransition(encodedRegionName, null);
+      processRegionInTransition(encodedRegionName, null, deadServers);
     }
   }
 
@@ -248,7 +274,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() &&
@@ -260,15 +287,18 @@ public class AssignmentManager extends Z
   }
 
   /**
-   * Process failover of <code>encodedName</code>.  Look in
+   * Process failover of new master for region <code>encodedRegionName</code>
+   * up in zookeeper.
    * @param encodedRegionName Region to process failover for.
    * @param encodedRegionName RegionInfo.  If null we'll go get it from meta 
table.
+   * @param deadServers Can be null 
    * @return
    * @throws KeeperException
    * @throws IOException
    */
   boolean processRegionInTransition(final String encodedRegionName,
-      final HRegionInfo regionInfo)
+      final HRegionInfo regionInfo,
+      final Map<String, List<Pair<HRegionInfo,Result>>> deadServers)
   throws KeeperException, IOException {
     RegionTransitionData data = ZKAssign.getData(watcher, encodedRegionName);
     if (data == null) return false;
@@ -279,12 +309,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<String, List<Pair<HRegionInfo,Result>>> deadServers)
   throws KeeperException {
     String encodedRegionName = regionInfo.getEncodedName();
     LOG.info("Processing region " + regionInfo.getRegionNameAsString() +
@@ -292,27 +323,32 @@ 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()));
+        }
         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()));
-        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()));
-        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(
@@ -322,24 +358,86 @@ 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, data.getStamp()));
-        HServerInfo hsi = serverManager.getServerInfo(data.getServerName());
+            regionInfo, RegionState.State.OPEN, data.getStamp()));
+        String sn = data.getServerName();
         // hsi could be null if this server is no longer online.  If
         // that the case, just let this RIT timeout; it'll be assigned
         // to new server then.
-        if (hsi == null) {
+        if (sn == null) {
           LOG.warn("Region in transition " + regionInfo.getEncodedName() +
             " references a server no longer up " + data.getServerName() +
             "; letting RIT timeout so will be assigned elsewhere");
           break;
         }
-        new OpenedRegionHandler(master, this, regionInfo, hsi).process();
+        if (isOnDeadServer(regionInfo, deadServers)) {
+          // If was on a dead server, then its not open any more; needs 
handling.
+          forceOffline(regionInfo, data);
+        } else {
+          HServerInfo hsi = this.serverManager.getServerInfo(sn);
+          if (hsi == null) {
+            LOG.info("Failed to find " + sn +
+              " in list of online servers; skipping registration of open of " +
+              regionInfo.getRegionNameAsString());
+          } else {
+            new OpenedRegionHandler(master, this, regionInfo, hsi).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()));
+    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<String, List<Pair<HRegionInfo, Result>>> deadServers) {
+    if (deadServers == null) return false;
+    for (Map.Entry<String, 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.
@@ -363,7 +461,7 @@ public class AssignmentManager extends Z
       if (!serverManager.isServerOnline(data.getServerName()) &&
           !this.master.getServerName().equals(data.getServerName())) {
         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());
@@ -1409,13 +1507,13 @@ public class AssignmentManager extends Z
    *         in META
    * @throws IOException
    */
-  private Map<HServerInfo,List<Pair<HRegionInfo,Result>>> rebuildUserRegions()
+  private Map<String, List<Pair<HRegionInfo,Result>>> rebuildUserRegions()
   throws IOException {
     // Region assignment from META
     List<Result> results = MetaReader.fullScanOfResults(catalogTracker);
     // Map of offline servers and their regions to be returned
-    Map<HServerInfo,List<Pair<HRegionInfo,Result>>> offlineServers =
-      new TreeMap<HServerInfo,List<Pair<HRegionInfo,Result>>>();
+    Map<String, List<Pair<HRegionInfo,Result>>> offlineServers =
+      new TreeMap<String, List<Pair<HRegionInfo,Result>>>();
     // Iterate regions in META
     for (Result result : results) {
       Pair<HRegionInfo,HServerInfo> region =
@@ -1427,14 +1525,13 @@ public class AssignmentManager extends Z
         // Region not being served, add to region map with no assignment
         // If this needs to be assigned out, it will also be in ZK as RIT
         this.regions.put(regionInfo, null);
-      } else if (!serverManager.isServerOnline(
-          regionLocation.getServerName())) {
+      } else if 
(!serverManager.isServerOnline(regionLocation.getServerName())) {
         // Region is located on a server that isn't online
         List<Pair<HRegionInfo,Result>> offlineRegions =
-          offlineServers.get(regionLocation);
+          offlineServers.get(regionLocation.getServerName());
         if (offlineRegions == null) {
           offlineRegions = new ArrayList<Pair<HRegionInfo,Result>>(1);
-          offlineServers.put(regionLocation, offlineRegions);
+          offlineServers.put(regionLocation.getServerName(), offlineRegions);
         }
         offlineRegions.add(new Pair<HRegionInfo,Result>(regionInfo, result));
       } else {
@@ -1460,9 +1557,9 @@ public class AssignmentManager extends Z
    * @throws KeeperException
    */
   private void processDeadServers(
-      Map<HServerInfo, List<Pair<HRegionInfo, Result>>> deadServers)
+      Map<String, List<Pair<HRegionInfo, Result>>> deadServers)
   throws IOException, KeeperException {
-    for (Map.Entry<HServerInfo, List<Pair<HRegionInfo,Result>>> deadServer :
+    for (Map.Entry<String, List<Pair<HRegionInfo,Result>>> deadServer :
       deadServers.entrySet()) {
       List<Pair<HRegionInfo,Result>> regions = deadServer.getValue();
       for (Pair<HRegionInfo,Result> region : regions) {
@@ -1471,10 +1568,10 @@ 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()); 
           }

Modified: 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/HMaster.java 
(original)
+++ 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/HMaster.java 
Tue Jun 21 20:28:56 2011
@@ -25,7 +25,6 @@ import java.lang.reflect.InvocationTarge
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
@@ -55,8 +54,8 @@ import org.apache.hadoop.hbase.catalog.M
 import org.apache.hadoop.hbase.client.HConnection;
 import org.apache.hadoop.hbase.client.HConnectionManager;
 import org.apache.hadoop.hbase.client.MetaScanner;
-import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
+import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.executor.ExecutorService.ExecutorType;
 import org.apache.hadoop.hbase.ipc.HBaseRPC;
@@ -87,7 +86,6 @@ import org.apache.hadoop.hbase.zookeeper
 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
 import org.apache.hadoop.io.MapWritable;
 import org.apache.hadoop.io.Text;
-import org.apache.hadoop.ipc.RemoteException;
 import org.apache.hadoop.net.DNS;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Watcher;

Modified: 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
 (original)
+++ 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
 Tue Jun 21 20:28:56 2011
@@ -277,8 +277,12 @@ public class ServerManager {
       // handleSplitReport will work. TODO: FIx!!
       if (msgs.length > 0)
         throw new PleaseHoldException("FIX! Putting off " +
-          "message processing because not yet rwady but possible we won't be " 
+
+          "message processing because not yet ready but possible we won't be " 
+
           "ready next on next report");
+
+      if (storedInfo == null) {
+        storedInfo = this.onlineServers.get(info.getServerName());
+      }
     }
 
     // Check startcodes

Modified: 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java
 (original)
+++ 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java
 Tue Jun 21 20:28:56 2011
@@ -823,7 +823,7 @@ public class MemStore implements HeapSiz
   }
 
   public final static long FIXED_OVERHEAD = ClassSize.align(
-      ClassSize.OBJECT + (11 * ClassSize.REFERENCE));
+      ClassSize.OBJECT + (12 * ClassSize.REFERENCE));
 
   public final static long DEEP_OVERHEAD = ClassSize.align(FIXED_OVERHEAD +
       ClassSize.REENTRANT_LOCK + ClassSize.ATOMIC_LONG +

Modified: 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java?rev=1138169&r1=1138168&r2=1138169&view=diff
==============================================================================
--- 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java
 (original)
+++ 
hbase/branches/0.90/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKAssign.java
 Tue Jun 21 20:28:56 2011
@@ -401,9 +401,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;
     }


Reply via email to