You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2009/05/20 07:05:04 UTC

svn commit: r776550 - in /hadoop/hbase/trunk_on_hadoop-0.18.3: ./ src/java/org/apache/hadoop/hbase/ src/java/org/apache/hadoop/hbase/master/ src/java/org/apache/hadoop/hbase/regionserver/

Author: apurtell
Date: Wed May 20 05:05:03 2009
New Revision: 776550

URL: http://svn.apache.org/viewvc?rev=776550&view=rev
Log:
HBASE-1440, HBASE-1441, HBASE-1430

Modified:
    hadoop/hbase/trunk_on_hadoop-0.18.3/CHANGES.txt
    hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/HConstants.java
    hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java
    hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/RegionManager.java
    hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ServerManager.java
    hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/regionserver/HLog.java

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/CHANGES.txt?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/CHANGES.txt (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/CHANGES.txt Wed May 20 05:05:03 2009
@@ -141,6 +141,9 @@
    HBASE-1435  HRegionServer is using wrong info bind address from
                hbase-site.xml (Lars George via Stack)
    HBASE-1438  HBASE-1421 broke the build (#602 up on hudson)
+   HBASE-1440  master won't go down because joined on a rootscanner that is
+               waiting for ever
+   HBASE-1441  NPE in ProcessRegionStatusChange#getMetaRegion
 
   IMPROVEMENTS
    HBASE-1089  Add count of regions on filesystem to master UI; add percentage
@@ -268,6 +271,7 @@
                minutes/hours
    HBASE-1420  add abliity to add and remove (table) indexes on existing
                tables (Clint Morgan via Stack)
+   HBASE-1430  Read the logs in batches during log splitting to avoid OOME
 
   OPTIMIZATIONS
    HBASE-1412  Change values for delete column and column family in KeyValue

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/HConstants.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/HConstants.java?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/HConstants.java (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/HConstants.java Wed May 20 05:05:03 2009
@@ -137,6 +137,10 @@
    *  to rewrite the logs. More means faster but bigger mem consumption */
   static final int DEFAULT_NUMBER_LOG_WRITER_THREAD = 10;
   
+  /** Default number of logs to read concurrently
+   *  when log splitting. More means faster but bigger mem consumption  */
+  static final int DEFAULT_NUMBER_CONCURRENT_LOG_READS = 10;
+  
   // Always store the location of the root table's HRegion.
   // This HRegion is never split.
   

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java Wed May 20 05:05:03 2009
@@ -71,8 +71,10 @@
     } else {
       this.metaRegion =
         master.regionManager.getFirstMetaRegionForRegion(regionInfo);
-      this.metaRegionName = this.metaRegion.getRegionName();
+      if (this.metaRegion != null) {
+        this.metaRegionName = this.metaRegion.getRegionName();
+      }
     }
     return this.metaRegion;
   }
-}
\ No newline at end of file
+}

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/RegionManager.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/RegionManager.java?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/RegionManager.java (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/RegionManager.java Wed May 20 05:05:03 2009
@@ -978,7 +978,8 @@
         // regionServerReport message from the HRegionServer that has been
         // allocated the ROOT region below.
         try {
-          rootRegionLocation.wait();
+          // Cycle rather than hold here in case master is closed meantime.
+          rootRegionLocation.wait(this.master.threadWakeFrequency);
         } catch (InterruptedException e) {
           // continue
         }
@@ -1350,4 +1351,4 @@
       return Bytes.compareTo(getRegionName(), o.getRegionName());
     }
   }
-}
\ No newline at end of file
+}

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ServerManager.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ServerManager.java?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ServerManager.java (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/master/ServerManager.java Wed May 20 05:05:03 2009
@@ -110,15 +110,22 @@
       int numServers = serverAddressToServerInfo.size();
       int numDeadServers = deadServers.size();
       double averageLoad = getAverageLoad();
-      LOG.info(numServers + " region servers, " + numDeadServers + 
-        " dead, average load " + averageLoad);
+      String deadServersList = null;
       if (numDeadServers > 0) {
-        LOG.info("DEAD [");
+        StringBuilder sb = new StringBuilder("Dead Server [");
+        boolean first = true;
         for (String server: deadServers) {
-          LOG.info("  " + server);
+          if (!first) {
+            sb.append(",  ");
+            first = false;
+          }
+          sb.append(server);
         }
-        LOG.info("]");
+        sb.append("]");
+        deadServersList = sb.toString();
       }
+      LOG.info(numServers + " region servers, " + numDeadServers + 
+        " dead, average load " + averageLoad + (deadServersList != null? deadServers: ""));
     }
     
   }
@@ -411,7 +418,7 @@
     for (int i = 0; i < incomingMsgs.length; i++) {
       HRegionInfo region = incomingMsgs[i].getRegionInfo();
       LOG.info("Received " + incomingMsgs[i] + " from " +
-        serverInfo.getServerName() + "; " + i + " of " + incomingMsgs.length);
+        serverInfo.getServerName() + "; " + (i + 1) + " of " + incomingMsgs.length);
       switch (incomingMsgs[i].getType()) {
         case MSG_REPORT_PROCESS_OPEN:
           openingCount++;

Modified: hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/regionserver/HLog.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/regionserver/HLog.java?rev=776550&r1=776549&r2=776550&view=diff
==============================================================================
--- hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/regionserver/HLog.java (original)
+++ hadoop/hbase/trunk_on_hadoop-0.18.3/src/java/org/apache/hadoop/hbase/regionserver/HLog.java Wed May 20 05:05:03 2009
@@ -774,147 +774,155 @@
   throws IOException {
     final Map<byte [], SequenceFile.Writer> logWriters =
       new TreeMap<byte [], SequenceFile.Writer>(Bytes.BYTES_COMPARATOR);
-    final Map<byte[], LinkedList<HLogEntry>> logEntries = 
-      new TreeMap<byte[], LinkedList<HLogEntry>>(Bytes.BYTES_COMPARATOR);
+    
     try {
-      for (int i = 0; i < logfiles.length; i++) {
-        if (LOG.isDebugEnabled()) {
-          LOG.debug("Splitting hlog " + (i + 1) + " of " + logfiles.length +
-            ": " + logfiles[i].getPath() + ", length=" + logfiles[i].getLen());
-        }
-        // Check for possibly empty file. With appends, currently Hadoop reports
-        // a zero length even if the file has been sync'd. Revisit if 
-        // HADOOP-4751 is committed.
-        long length = logfiles[i].getLen();
-        HLogKey key = new HLogKey();
-        KeyValue val = new KeyValue();
-        SequenceFile.Reader in = null;
-        try {
-          in = new SequenceFile.Reader(fs, logfiles[i].getPath(), conf);
+      int maxSteps = Double.valueOf(Math.ceil((logfiles.length * 1.0) / 
+          DEFAULT_NUMBER_CONCURRENT_LOG_READS)).intValue();
+      for(int step = 0; step < maxSteps; step++) {
+        final Map<byte[], LinkedList<HLogEntry>> logEntries = 
+          new TreeMap<byte[], LinkedList<HLogEntry>>(Bytes.BYTES_COMPARATOR);
+        // Stop at logfiles.length when it's the last step
+        int endIndex = step == maxSteps - 1? logfiles.length: 
+          step * DEFAULT_NUMBER_CONCURRENT_LOG_READS +
+          DEFAULT_NUMBER_CONCURRENT_LOG_READS;
+        for (int i = (step * 10); i < endIndex; i++) {
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Splitting hlog " + (i + 1) + " of " + logfiles.length +
+                ": " + logfiles[i].getPath() + 
+                ", length=" + logfiles[i].getLen());
+          }
+          // Check for possibly empty file. With appends, currently Hadoop 
+          // reports a zero length even if the file has been sync'd. Revisit if
+          // HADOOP-4751 is committed.
+          long length = logfiles[i].getLen();
+          HLogKey key = new HLogKey();
+          KeyValue val = new KeyValue();
+          SequenceFile.Reader in = null;
+              int count = 0;
           try {
-            int count = 0;
-            while (in.next(key, val)) {
-              byte [] regionName = key.getRegionName();
-              LinkedList<HLogEntry> queue = logEntries.get(regionName);
-              if (queue == null) {
-                queue = new LinkedList<HLogEntry>();
-                LOG.debug("Adding queue for " + Bytes.toString(regionName));
-                logEntries.put(regionName, queue);
+            in = new SequenceFile.Reader(fs, logfiles[i].getPath(), conf);
+            try {
+              while (in.next(key, val)) {
+                byte [] regionName = key.getRegionName();
+                LinkedList<HLogEntry> queue = logEntries.get(regionName);
+                if (queue == null) {
+                  queue = new LinkedList<HLogEntry>();
+                  LOG.debug("Adding queue for " + Bytes.toString(regionName));
+                  logEntries.put(regionName, queue);
+                }
+                queue.push(new HLogEntry(val, key));
+                count++;
+              }
+              LOG.debug("Pushed " + count + " entries from " +
+                logfiles[i].getPath());
+            } catch (IOException e) {
+              LOG.debug("IOE Pushed " + count + " entries from " +
+                logfiles[i].getPath());
+              e = RemoteExceptionHandler.checkIOException(e);
+              if (!(e instanceof EOFException)) {
+                LOG.warn("Exception processing " + logfiles[i].getPath() +
+                    " -- continuing. Possible DATA LOSS!", e);
               }
-              queue.push(new HLogEntry(val, key));
-              count++;
             }
-            LOG.debug("Pushed " + count + " entries from " +
-              logfiles[i].getPath());
           } catch (IOException e) {
-            e = RemoteExceptionHandler.checkIOException(e);
-            if (!(e instanceof EOFException)) {
-              LOG.warn("Exception processing " + logfiles[i].getPath() +
-                  " -- continuing. Possible DATA LOSS!", e);
+            if (length <= 0) {
+              LOG.warn("Empty hlog, continuing: " + logfiles[i]);
+              continue;
             }
-          }
-        } catch (IOException e) {
-          if (length <= 0) {
-            LOG.warn("Empty hlog, continuing: " + logfiles[i]);
-            continue;
-          }
-          throw e;
-        } finally {
-          try {
-            if (in != null) {
-              in.close();
+            throw e;
+          } finally {
+            try {
+              if (in != null) {
+                in.close();
+              }
+            } catch (IOException e) {
+              LOG.warn("Close in finally threw exception -- continuing", e);
             }
-          } catch (IOException e) {
-            LOG.warn("Close in finally threw exception -- continuing", e);
+            // Delete the input file now so we do not replay edits. We could
+            // have gotten here because of an exception. If so, probably
+            // nothing we can do about it. Replaying it, it could work but we
+            // could be stuck replaying for ever. Just continue though we
+            // could have lost some edits.
+            fs.delete(logfiles[i].getPath(), true);
           }
-          // Delete the input file now so we do not replay edits. We could
-          // have gotten here because of an exception. If so, probably
-          // nothing we can do about it. Replaying it, it could work but we
-          // could be stuck replaying for ever. Just continue though we
-          // could have lost some edits.
-          fs.delete(logfiles[i].getPath(), true);
         }
-      }
-      ExecutorService threadPool = 
-        Executors.newFixedThreadPool(DEFAULT_NUMBER_LOG_WRITER_THREAD);
-      for (final byte[] key : logEntries.keySet()) {
+        ExecutorService threadPool = 
+          Executors.newFixedThreadPool(DEFAULT_NUMBER_LOG_WRITER_THREAD);
+        for (final byte[] key : logEntries.keySet()) {
 
-        Thread thread = new Thread(Bytes.toString(key)) {
-          public void run() {
-            LinkedList<HLogEntry> entries = logEntries.get(key);
-            LOG.debug("Thread got " + entries.size() + " to process");
-            long threadTime = System.currentTimeMillis();
-            try {
-              int count = 0;
-              for (HLogEntry logEntry : entries) {
-                SequenceFile.Writer w = logWriters.get(key);
-                if (w == null) {
-                  Path logfile = new Path(HRegion.getRegionDir(HTableDescriptor
-                      .getTableDir(rootDir, logEntry.getKey().getTablename()),
-                      HRegionInfo.encodeRegionName(key)),
-                      HREGION_OLDLOGFILE_NAME);
-                  Path oldlogfile = null;
-                  SequenceFile.Reader old = null;
-                  if (fs.exists(logfile)) {
-                    LOG.warn("Old hlog file " + logfile
+          Thread thread = new Thread(Bytes.toString(key)) {
+            public void run() {
+              LinkedList<HLogEntry> entries = logEntries.get(key);
+              LOG.debug("Thread got " + entries.size() + " to process");
+              long threadTime = System.currentTimeMillis();
+              try {
+                int count = 0;
+                for (HLogEntry logEntry : entries) {
+                  SequenceFile.Writer w = logWriters.get(key);
+                  if (w == null) {
+                    Path logfile = new Path(HRegion.getRegionDir(HTableDescriptor
+                        .getTableDir(rootDir, logEntry.getKey().getTablename()),
+                        HRegionInfo.encodeRegionName(key)),
+                        HREGION_OLDLOGFILE_NAME);
+                    Path oldlogfile = null;
+                    SequenceFile.Reader old = null;
+                    if (fs.exists(logfile)) {
+                      LOG.warn("Old hlog file " + logfile
                         + " already exists. Copying existing file to new file");
-                    oldlogfile = new Path(logfile.toString() + ".old");
-                    fs.rename(logfile, oldlogfile);
-                    old = new SequenceFile.Reader(fs, oldlogfile, conf);
-                  }
-                  w = SequenceFile.createWriter(fs, conf, logfile,
-                      HLogKey.class, KeyValue.class, getCompressionType(conf));
-                  // Use copy of regionName; regionName object is reused inside
-                  // in
-                  // HStoreKey.getRegionName so its content changes as we
-                  // iterate.
-                  logWriters.put(key, w);
-                  if (LOG.isDebugEnabled()) {
-                    LOG.debug("Creating new hlog file writer for path "
-                        + logfile + " and region " + Bytes.toString(key));
-                  }
+                      oldlogfile = new Path(logfile.toString() + ".old");
+                      fs.rename(logfile, oldlogfile);
+                      old = new SequenceFile.Reader(fs, oldlogfile, conf);
+                    }
+                    w = SequenceFile.createWriter(fs, conf, logfile,
+                        HLogKey.class, KeyValue.class, getCompressionType(conf));
+                    logWriters.put(key, w);
+                    if (LOG.isDebugEnabled()) {
+                      LOG.debug("Creating new hlog file writer for path "
+                          + logfile + " and region " + Bytes.toString(key));
+                    }
 
-                  if (old != null) {
-                    // Copy from existing log file
-                    HLogKey oldkey = new HLogKey();
-                    KeyValue oldval = new KeyValue();
-                    for (; old.next(oldkey, oldval); count++) {
-                      if (LOG.isDebugEnabled() && count > 0
-                          && count % 10000 == 0) {
-                        LOG.debug("Copied " + count + " edits");
+                    if (old != null) {
+                      // Copy from existing log file
+                      HLogKey oldkey = new HLogKey();
+                      KeyValue oldval = new KeyValue();
+                      for (; old.next(oldkey, oldval); count++) {
+                        if (LOG.isDebugEnabled() && count > 0
+                            && count % 10000 == 0) {
+                          LOG.debug("Copied " + count + " edits");
+                        }
+                        w.append(oldkey, oldval);
                       }
-                      w.append(oldkey, oldval);
+                      old.close();
+                      fs.delete(oldlogfile, true);
                     }
-                    old.close();
-                    fs.delete(oldlogfile, true);
                   }
+                  w.append(logEntry.getKey(), logEntry.getEdit());
+                  count++;
                 }
-                w.append(logEntry.getKey(), logEntry.getEdit());
-                count++;
-              }
-              if (LOG.isDebugEnabled()) {
-                LOG.debug("Applied " + count + " total edits to "
-                    + Bytes.toString(key) + " in "
-                    + (System.currentTimeMillis() - threadTime) + "ms");
+                if (LOG.isDebugEnabled()) {
+                  LOG.debug("Applied " + count + " total edits to "
+                      + Bytes.toString(key) + " in "
+                      + (System.currentTimeMillis() - threadTime) + "ms");
+                }
+              } catch (IOException e) {
+                e = RemoteExceptionHandler.checkIOException(e);
+                LOG.warn("Got while writing region " + Bytes.toString(key)
+                    + " log " + e);
+                e.printStackTrace();
               }
-            } catch (IOException e) {
-              e = RemoteExceptionHandler.checkIOException(e);
-              LOG.warn("Got while writing region " + Bytes.toString(key)
-                  + " log " + e);
-              e.printStackTrace();
             }
+          };
+          threadPool.execute(thread);
+        }
+        threadPool.shutdown();
+        // Wait for all threads to terminate
+        try {
+          for(int i = 0; !threadPool.awaitTermination(5, TimeUnit.SECONDS); i++) {
+            LOG.debug("Waiting for hlog writers to terminate, iteration #" + i);
           }
-        };
-        threadPool.execute(thread);
-      }
-      threadPool.shutdown();
-      // Wait for all threads to terminate
-      try {
-        for(int i = 0; !threadPool.awaitTermination(5, TimeUnit.SECONDS) ; i++) {
-          LOG.debug("Waiting for hlog writers to terminate, iteration #" + i);
+        }catch(InterruptedException ex) {
+          LOG.warn("Hlog writers were interrupted, possible data loss!");
         }
-      }catch(InterruptedException ex) {
-        LOG.warn("Hlog writers were interrupted, possible data loss!");
       }
     } finally {
       for (SequenceFile.Writer w : logWriters.values()) {