MAPREDUCE-2470. Fix NPE in RunningJobs::getCounters.
Contributed by Robert Joseph Evans


git-svn-id: https://svn.apache.org/repos/asf/hadoop/mapreduce/trunk@1125578 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES.txt b/CHANGES.txt
index ba58687..e1eb16d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -214,6 +214,9 @@
     MAPREDUCE-2518. The t flag is missing in distcp help message.  (Wei Yongjun
     via szetszwo)
 
+    MAPREDUCE-2470. Fix NPE in RunningJobs::getCounters. (Robert Joseph Evans
+    via cdouglas)
+
 Release 0.22.0 - Unreleased
 
   INCOMPATIBLE CHANGES
diff --git a/src/java/org/apache/hadoop/mapred/JobClient.java b/src/java/org/apache/hadoop/mapred/JobClient.java
index 5d0f50b..3b5f84b 100644
--- a/src/java/org/apache/hadoop/mapred/JobClient.java
+++ b/src/java/org/apache/hadoop/mapred/JobClient.java
@@ -42,8 +42,6 @@
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.Text;
-import org.apache.hadoop.ipc.RemoteException;
-import org.apache.hadoop.security.AccessControlException;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.SecretManager.InvalidToken;
 import org.apache.hadoop.util.Tool;
@@ -149,7 +147,7 @@
    * a JobProfile object to provide some info, and interacts with the
    * remote service to provide certain functionality.
    */
-  class NetworkedJob implements RunningJob {
+  static class NetworkedJob implements RunningJob {
     Job job;
     /**
      * We store a JobProfile and a timestamp for when we last
@@ -158,7 +156,7 @@
      * has completely forgotten about the job.  (eg, 24 hours after the
      * job completes.)
      */
-    public NetworkedJob(JobStatus status) throws IOException {
+    public NetworkedJob(JobStatus status, Cluster cluster) throws IOException {
       job = Job.getInstance(cluster, status, new JobConf(status.getJobFile()));
     }
 
@@ -380,7 +378,12 @@
      */
     public Counters getCounters() throws IOException {
       try { 
-        return Counters.downgrade(job.getCounters());
+        Counters result = null;
+        org.apache.hadoop.mapreduce.Counters temp = job.getCounters();
+        if(temp != null) {
+          result = Counters.downgrade(temp);
+        }
+        return result;
       } catch (InterruptedException ie) {
         throw new IOException(ie);
       }
@@ -557,7 +560,7 @@
       if (job != null) {
         JobStatus status = JobStatus.downgrade(job.getStatus());
         if (status != null) {
-          return new NetworkedJob(status);
+          return new NetworkedJob(status, cluster);
         } 
       }
     } catch (InterruptedException ie) {
diff --git a/src/java/org/apache/hadoop/mapred/RunningJob.java b/src/java/org/apache/hadoop/mapred/RunningJob.java
index c2a1695..b3af4f6 100644
--- a/src/java/org/apache/hadoop/mapred/RunningJob.java
+++ b/src/java/org/apache/hadoop/mapred/RunningJob.java
@@ -193,7 +193,7 @@
   /**
    * Gets the counters for this job.
    * 
-   * @return the counters for this job.
+   * @return the counters for this job or null if the job has been retired.
    * @throws IOException
    */
   public Counters getCounters() throws IOException;
diff --git a/src/java/org/apache/hadoop/mapreduce/protocol/ClientProtocol.java b/src/java/org/apache/hadoop/mapreduce/protocol/ClientProtocol.java
index ac5275a..80e556b 100644
--- a/src/java/org/apache/hadoop/mapreduce/protocol/ClientProtocol.java
+++ b/src/java/org/apache/hadoop/mapreduce/protocol/ClientProtocol.java
@@ -230,7 +230,7 @@
   
   /**
    * Get task completion events for the jobid, starting from fromEventId. 
-   * Returns empty aray if no events are available. 
+   * Returns empty array if no events are available. 
    * @param jobid job id 
    * @param fromEventId event id to start from.
    * @param maxEvents the max number of events we want to look at 
diff --git a/src/test/mapred/org/apache/hadoop/mapred/TestNetworkedJob.java b/src/test/mapred/org/apache/hadoop/mapred/TestNetworkedJob.java
new file mode 100644
index 0000000..b6565e2
--- /dev/null
+++ b/src/test/mapred/org/apache/hadoop/mapred/TestNetworkedJob.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.mapred;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.apache.hadoop.mapreduce.Job;
+import org.junit.Test;
+import static org.mockito.Mockito.*;
+
+
+public class TestNetworkedJob {
+
+  @SuppressWarnings("deprecation")
+  @Test
+  public void testGetNullCounters() throws Exception {
+    //mock creation
+    Job mockJob = mock(Job.class);
+    RunningJob underTest = new JobClient.NetworkedJob(mockJob); 
+
+    when(mockJob.getCounters()).thenReturn(null);
+    assertNull(underTest.getCounters());
+    //verification
+    verify(mockJob).getCounters();
+  }
+}