浏览代码

YARN-2251. Avoid negative elapsed time in JHS/MRAM web UI and services (Contributed by Zhijie Shen)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1607833 13f79535-47bb-0310-9956-ffa450edef68
Junping Du 11 年之前
父节点
当前提交
4074843fea

+ 3 - 0
hadoop-yarn-project/CHANGES.txt

@@ -33,6 +33,9 @@ Release 2.6.0 - UNRELEASED
 
   BUG FIXES
 
+    YARN-2251. Avoid negative elapsed time in JHS/MRAM web UI and services.
+    (Zhijie Shen via junping_du)
+
 Release 2.5.0 - UNRELEASED
 
   INCOMPATIBLE CHANGES

+ 24 - 2
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/Times.java

@@ -21,10 +21,14 @@ package org.apache.hadoop.yarn.util;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience.Private;
 
 @Private
 public class Times {
+  private static final Log LOG = LogFactory.getLog(Times.class);
+
   static final ThreadLocal<SimpleDateFormat> dateFormat =
       new ThreadLocal<SimpleDateFormat>() {
         @Override protected SimpleDateFormat initialValue() {
@@ -36,12 +40,30 @@ public class Times {
     return Times.elapsed(started, finished, true);
   }
 
+  // A valid elapsed is supposed to be non-negative. If finished/current time
+  // is ahead of the started time, return -1 to indicate invalid elapsed time,
+  // and record a warning log.
   public static long elapsed(long started, long finished, boolean isRunning) {
     if (finished > 0 && started > 0) {
-      return finished - started;
+      long elapsed = finished - started;
+      if (elapsed >= 0) {
+        return elapsed;
+      } else {
+        LOG.warn("Finished time " + finished
+            + " is ahead of started time " + started);
+        return -1;
+      }
     }
     if (isRunning) {
-      return started > 0 ? System.currentTimeMillis() - started : 0;
+      long current = System.currentTimeMillis();
+      long elapsed = started > 0 ? current - started : 0;
+      if (elapsed >= 0) {
+        return elapsed;
+      } else {
+        LOG.warn("Current time " + current
+            + " is ahead of started time " + started);
+        return -1;
+      }
     } else {
       return -1;
     }

+ 11 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestTimes.java

@@ -50,4 +50,15 @@ public class TestTimes {
     elapsed = Times.elapsed(5, 10, false);
     Assert.assertEquals("Elapsed time is not 5", 5, elapsed);
   }
+
+  @Test
+  public void testFinishTimesAheadOfStartTimes() {
+    long elapsed = Times.elapsed(10, 5, true);
+    Assert.assertEquals("Elapsed time is not -1", -1, elapsed);
+    elapsed = Times.elapsed(10, 5, false);
+    Assert.assertEquals("Elapsed time is not -1", -1, elapsed);
+    // use Long.MAX_VALUE to ensure started time is after the current one
+    elapsed = Times.elapsed(Long.MAX_VALUE, 0, true);
+    Assert.assertEquals("Elapsed time is not -1", -1, elapsed);
+  }
 }