hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From st...@apache.org
Subject svn commit: r810200 - in /hadoop/hbase/trunk: CHANGES.txt src/java/org/apache/hadoop/hbase/master/BaseScanner.java src/java/org/apache/hadoop/hbase/master/ServerManager.java
Date Tue, 01 Sep 2009 19:54:42 GMT
Author: stack
Date: Tue Sep  1 19:54:42 2009
New Revision: 810200

URL: http://svn.apache.org/viewvc?rev=810200&view=rev
Log:
HBASE-1784 Missing rows after medium intensity insert

Modified:
    hadoop/hbase/trunk/CHANGES.txt
    hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/BaseScanner.java
    hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/ServerManager.java

Modified: hadoop/hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=810200&r1=810199&r2=810200&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Tue Sep  1 19:54:42 2009
@@ -361,6 +361,7 @@
    HBASE-1767  test zookeeper broken in trunk and 0.20 branch; broken on
                hudson too
    HBASE-1780  HTable.flushCommits clears write buffer in finally clause
+   HBASE-1784  Missing rows after medium intensity insert
 
   IMPROVEMENTS
    HBASE-1089  Add count of regions on filesystem to master UI; add percentage

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/BaseScanner.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/BaseScanner.java?rev=810200&r1=810199&r2=810200&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/BaseScanner.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/BaseScanner.java Tue Sep  1
19:54:42 2009
@@ -39,6 +39,7 @@
 import org.apache.hadoop.hbase.RemoteExceptionHandler;
 import org.apache.hadoop.hbase.UnknownScannerException;
 import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.ipc.HRegionInterface;
@@ -153,8 +154,10 @@
     int rows = 0;
     try {
       regionServer = master.connection.getHRegionConnection(region.getServer());
-      scannerId = regionServer.openScanner(region.getRegionName(),
-        new Scan().addFamily(HConstants.CATALOG_FAMILY));
+      Scan s = new Scan().addFamily(HConstants.CATALOG_FAMILY);
+      // Make this scan do a row at a time otherwise, data can be stale.
+      s.setCaching(1);
+      scannerId = regionServer.openScanner(region.getRegionName(), s);
       while (true) {
         Result values = regionServer.next(scannerId);
         if (values == null || values.size() == 0) {
@@ -165,19 +168,11 @@
           emptyRows.add(values.getRow());
           continue;
         }
-        String serverName = "";
-        byte [] val = values.getValue(CATALOG_FAMILY, SERVER_QUALIFIER);
-        if( val != null) {
-          serverName = Bytes.toString(val);
-        }
-        long startCode = 0L;
-        val = values.getValue(CATALOG_FAMILY, STARTCODE_QUALIFIER);
-        if(val != null) {
-          startCode = Bytes.toLong(val);
-        }
+        String serverAddress = getServerAddress(values);
+        long startCode = getStartCode(values);
 
         // Note Region has been assigned.
-        checkAssigned(info, serverName, startCode);
+        checkAssigned(regionServer, region, info, serverAddress, startCode);
         if (isSplitParent(info)) {
           splitParents.put(info, values);
         }
@@ -231,6 +226,24 @@
   }
 
   /*
+   * @param r
+   * @return Empty String or server address found in <code>r</code>
+   */
+  private String getServerAddress(final Result r) {
+    byte [] val = r.getValue(CATALOG_FAMILY, SERVER_QUALIFIER);
+    return val == null || val.length <= 0? "": Bytes.toString(val);
+  }
+
+  /*
+   * @param r
+   * @return Return 0L or server startcode found in <code>r</code>
+   */
+  private long getStartCode(final Result r) {
+    byte [] val = r.getValue(CATALOG_FAMILY, STARTCODE_QUALIFIER);
+    return val == null || val.length <= 0? 0L: Bytes.toLong(val);
+  }
+
+  /*
    * @param info Region to check.
    * @return True if this is a split parent.
    */
@@ -326,8 +339,7 @@
     
     if (LOG.isDebugEnabled()) {
       LOG.debug(split.getRegionNameAsString() + "/" + split.getEncodedName()
-          + " no longer has references to " + Bytes.toStringBinary(parent)
-         );
+          + " no longer has references to " + Bytes.toStringBinary(parent));
     }
     
     Delete delete = new Delete(parent);
@@ -337,12 +349,43 @@
     return result;
   }
 
-  protected void checkAssigned(final HRegionInfo info,
+  /*
+   * Check the passed region is assigned.  If not, add to unassigned.
+   * @param regionServer
+   * @param meta
+   * @param info
+   * @param serverAddress
+   * @param startCode
+   * @throws IOException
+   */
+  protected void checkAssigned(final HRegionInterface regionServer,
+    final MetaRegion meta, final HRegionInfo info,
     final String serverAddress, final long startCode) 
   throws IOException {
     String serverName = null;
-    if (serverAddress != null && serverAddress.length() > 0) {
-      serverName = HServerInfo.getServerName(serverAddress, startCode);
+    String sa = serverAddress;
+    long sc = startCode;
+    if (sa == null || sa.length() <= 0) {
+      // Scans are sloppy.  They don't respect row locks and they get and 
+      // cache a row internally so may have data that is a little stale.  Make
+      // sure that for sure this serverAddress is null.  We are trying to
+      // avoid double-assignments.  See hbase-1784.  Will have to wait till
+      // 0.21 hbase where we use zk to mediate state transitions to do better.
+      Get g = new Get(info.getRegionName());
+      g.addFamily(HConstants.CATALOG_FAMILY);
+      Result r = regionServer.get(meta.getRegionName(), g);
+      if (r != null && !r.isEmpty()) {
+        sa = getServerAddress(r);
+        if (sa != null && sa.length() > 0) {
+          // Reget startcode in case its changed in the meantime too.
+          sc = getStartCode(r);
+          LOG.debug("GET got values when meta found none: serverAddress=" + sa
+              + ", startCode=" + sc);
+        }
+      }
+    }
+    if (sa != null && sa.length() > 0) {
+      serverName = HServerInfo.getServerName(sa, sc);
     }
     HServerInfo storedInfo = null;
     synchronized (this.master.regionManager) {
@@ -365,8 +408,8 @@
         // The current assignment is invalid
         if (LOG.isDebugEnabled()) {
           LOG.debug("Current assignment of " + info.getRegionNameAsString() +
-            " is not valid; " + " serverAddress=" + serverAddress +
-            ", startCode=" + startCode + " unknown.");
+            " is not valid; " + " serverAddress=" + sa +
+            ", startCode=" + sc + " unknown.");
         }
         // Now get the region assigned
         this.master.regionManager.setUnassigned(info, true);

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/ServerManager.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/ServerManager.java?rev=810200&r1=810199&r2=810200&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/ServerManager.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/master/ServerManager.java Tue Sep
 1 19:54:42 2009
@@ -44,6 +44,9 @@
 import org.apache.hadoop.hbase.HRegionLocation;
 import org.apache.hadoop.hbase.Leases;
 import org.apache.hadoop.hbase.HMsg.Type;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.ipc.HRegionInterface;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWrapper;
 import org.apache.zookeeper.WatchedEvent;
@@ -499,10 +502,8 @@
       // This prevents the master from sending a SPLIT message if the table
       // has already split by the region server. 
       master.regionManager.endActions(region.getRegionName());
-      HRegionInfo newRegionA = splitA.getRegionInfo();
-      master.regionManager.setUnassigned(newRegionA, false);
-      HRegionInfo newRegionB = splitB.getRegionInfo();
-      master.regionManager.setUnassigned(newRegionB, false);
+      assignSplitDaughter(splitA.getRegionInfo());
+      assignSplitDaughter(splitB.getRegionInfo());
       if (region.isMetaTable()) {
         // A meta region has split.
         master.regionManager.offlineMetaRegion(region.getStartKey());
@@ -512,6 +513,32 @@
   }
 
   /*
+   * Assign new daughter-of-a-split UNLESS its already been assigned.
+   * It could have been assigned already in rare case where there was a large
+   * gap between insertion of the daughter region into .META. by the
+   * splitting regionserver and receipt of the split message in master (See
+   * HBASE-1784).
+   * @param hri Region to assign.
+   */
+  private void assignSplitDaughter(final HRegionInfo hri) {
+    MetaRegion mr = this.master.regionManager.getFirstMetaRegionForRegion(hri);
+    Get g = new Get(hri.getRegionName());
+    g.addFamily(HConstants.CATALOG_FAMILY);
+    try {
+      HRegionInterface server =
+        master.connection.getHRegionConnection(mr.getServer());
+      Result r = server.get(mr.getRegionName(), g);
+      // If size > 3 -- presume regioninfo, startcode and server -- then presume
+      // that this daughter already assigned and return.
+      if (r.size() >= 3) return;
+    } catch (IOException e) {
+      LOG.warn("Failed get on " + HConstants.CATALOG_FAMILY_STR +
+        "; possible double-assignment?", e);
+    }
+    this.master.regionManager.setUnassigned(hri, false);
+  }
+
+  /*
    * Region server is reporting that a region is now opened
    * @param serverInfo
    * @param region



Mime
View raw message