001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.mapreduce;
019    
020    import java.io.DataInput;
021    import java.io.DataOutput;
022    import java.io.IOException;
023    import java.util.HashMap;
024    import java.util.Map;
025    import java.util.Map.Entry;
026    
027    import org.apache.hadoop.classification.InterfaceAudience;
028    import org.apache.hadoop.classification.InterfaceStability;
029    import org.apache.hadoop.io.Text;
030    import org.apache.hadoop.io.Writable;
031    import org.apache.hadoop.io.WritableFactories;
032    import org.apache.hadoop.io.WritableFactory;
033    import org.apache.hadoop.io.WritableUtils;
034    import org.apache.hadoop.security.authorize.AccessControlList;
035    
036    /**************************************************
037     * Describes the current status of a job.
038     **************************************************/
039    @InterfaceAudience.Public
040    @InterfaceStability.Evolving
041    public class JobStatus implements Writable, Cloneable {
042    
043      static {                                      // register a ctor
044        WritableFactories.setFactory
045          (JobStatus.class,
046           new WritableFactory() {
047             public Writable newInstance() { return new JobStatus(); }
048           });
049      }
050    
051      /**
052       * Current state of the job 
053       */
054      public static enum State {
055        RUNNING(1),
056        SUCCEEDED(2),
057        FAILED(3),
058        PREP(4),
059        KILLED(5);
060        
061        int value;
062        
063        State(int value) {
064          this.value = value;
065        }
066        
067        public int getValue() {
068          return value; 
069        }
070        
071      };
072      
073      private JobID jobid;
074      private float mapProgress;
075      private float reduceProgress;
076      private float cleanupProgress;
077      private float setupProgress;
078      private State runState;
079      private long startTime;
080      private String user;
081      private String queue;
082      private JobPriority priority;
083      private String schedulingInfo="NA";
084      private String failureInfo = "NA";
085    
086      private Map<JobACL, AccessControlList> jobACLs =
087          new HashMap<JobACL, AccessControlList>();
088    
089      private String jobName;
090      private String jobFile;
091      private long finishTime;
092      private boolean isRetired;
093      private String historyFile = "";
094      private String trackingUrl ="";
095      private int numUsedSlots;
096      private int numReservedSlots;
097      private int usedMem;
098      private int reservedMem;
099      private int neededMem;
100    
101        
102      /**
103       */
104      public JobStatus() {
105      }
106    
107      /**
108       * Create a job status object for a given jobid.
109       * @param jobid The jobid of the job
110       * @param setupProgress The progress made on the setup
111       * @param mapProgress The progress made on the maps
112       * @param reduceProgress The progress made on the reduces
113       * @param cleanupProgress The progress made on the cleanup
114       * @param runState The current state of the job
115       * @param jp Priority of the job.
116       * @param user userid of the person who submitted the job.
117       * @param jobName user-specified job name.
118       * @param jobFile job configuration file. 
119       * @param trackingUrl link to the web-ui for details of the job.
120       */
121       public JobStatus(JobID jobid, float setupProgress, float mapProgress,
122                        float reduceProgress, float cleanupProgress, 
123                        State runState, JobPriority jp, String user, String jobName, 
124                        String jobFile, String trackingUrl) {
125         this(jobid, setupProgress, mapProgress, reduceProgress, cleanupProgress, 
126             runState, jp, user, jobName, "default", jobFile, trackingUrl);
127       }
128               
129       /**
130        * Create a job status object for a given jobid.
131        * @param jobid The jobid of the job
132        * @param setupProgress The progress made on the setup
133        * @param mapProgress The progress made on the maps
134        * @param reduceProgress The progress made on the reduces
135        * @param cleanupProgress The progress made on the cleanup
136        * @param runState The current state of the job
137        * @param jp Priority of the job.
138        * @param user userid of the person who submitted the job.
139        * @param jobName user-specified job name.
140        * @param queue queue name
141        * @param jobFile job configuration file. 
142        * @param trackingUrl link to the web-ui for details of the job.
143        */
144        public JobStatus(JobID jobid, float setupProgress, float mapProgress,
145                         float reduceProgress, float cleanupProgress, 
146                         State runState, JobPriority jp, 
147                         String user, String jobName, String queue, 
148                         String jobFile, String trackingUrl) {
149          this.jobid = jobid;
150          this.setupProgress = setupProgress;
151          this.mapProgress = mapProgress;
152          this.reduceProgress = reduceProgress;
153          this.cleanupProgress = cleanupProgress;
154          this.runState = runState;
155          this.user = user;
156          this.queue = queue;
157          if (jp == null) {
158            throw new IllegalArgumentException("Job Priority cannot be null.");
159          }
160          priority = jp;
161          this.jobName = jobName;
162          this.jobFile = jobFile;
163          this.trackingUrl = trackingUrl;
164        }
165        
166    
167      /**
168       * Sets the map progress of this job
169       * @param p The value of map progress to set to
170       */
171      protected synchronized void setMapProgress(float p) { 
172        this.mapProgress = (float) Math.min(1.0, Math.max(0.0, p)); 
173      }
174    
175      /**
176       * Sets the cleanup progress of this job
177       * @param p The value of cleanup progress to set to
178       */
179      protected synchronized void setCleanupProgress(float p) { 
180        this.cleanupProgress = (float) Math.min(1.0, Math.max(0.0, p)); 
181      }
182    
183      /**
184       * Sets the setup progress of this job
185       * @param p The value of setup progress to set to
186       */
187      protected synchronized void setSetupProgress(float p) { 
188        this.setupProgress = (float) Math.min(1.0, Math.max(0.0, p)); 
189      }
190    
191      /**
192       * Sets the reduce progress of this Job
193       * @param p The value of reduce progress to set to
194       */
195      protected synchronized void setReduceProgress(float p) { 
196        this.reduceProgress = (float) Math.min(1.0, Math.max(0.0, p)); 
197      }
198        
199      /**
200       * Set the priority of the job, defaulting to NORMAL.
201       * @param jp new job priority
202       */
203      protected synchronized void setPriority(JobPriority jp) {
204        if (jp == null) {
205          throw new IllegalArgumentException("Job priority cannot be null.");
206        }
207        priority = jp;
208      }
209      
210      /** 
211       * Set the finish time of the job
212       * @param finishTime The finishTime of the job
213       */
214      protected synchronized void setFinishTime(long finishTime) {
215        this.finishTime = finishTime;
216      }
217    
218      /**
219       * Set the job history file url for a completed job
220       */
221      protected synchronized void setHistoryFile(String historyFile) {
222        this.historyFile = historyFile;
223      }
224    
225      /**
226       * Set the link to the web-ui for details of the job.
227       */
228      protected synchronized void setTrackingUrl(String trackingUrl) {
229        this.trackingUrl = trackingUrl;
230      }
231    
232      /**
233       * Set the job retire flag to true.
234       */
235      protected synchronized void setRetired() {
236        this.isRetired = true;
237      }
238    
239      /**
240       * Change the current run state of the job.
241       */
242      protected synchronized void setState(State state) {
243        this.runState = state;
244      }
245    
246      /** 
247       * Set the start time of the job
248       * @param startTime The startTime of the job
249       */
250      protected synchronized void setStartTime(long startTime) { 
251        this.startTime = startTime;
252      }
253        
254      /**
255       * @param userName The username of the job
256       */
257      protected synchronized void setUsername(String userName) { 
258        this.user = userName;
259      }
260    
261      /**
262       * Used to set the scheduling information associated to a particular Job.
263       * 
264       * @param schedulingInfo Scheduling information of the job
265       */
266      protected synchronized void setSchedulingInfo(String schedulingInfo) {
267        this.schedulingInfo = schedulingInfo;
268      }
269    
270      /**
271       * Set the job acls.
272       * 
273       * @param acls {@link Map} from {@link JobACL} to {@link AccessControlList}
274       */
275      protected synchronized void setJobACLs(Map<JobACL, AccessControlList> acls) {
276        this.jobACLs = acls;
277      }
278    
279      /**
280       * Set queue name
281       * @param queue queue name
282       */
283      protected synchronized void setQueue(String queue) {
284        this.queue = queue;
285      }
286    
287      /**
288       * Set diagnostic information.
289       * @param failureInfo diagnostic information
290       */
291      protected synchronized void setFailureInfo(String failureInfo) {
292        this.failureInfo = failureInfo;
293      }
294      
295      /**
296       * Get queue name
297       * @return queue name
298       */
299      public synchronized String getQueue() {
300        return queue;
301      }
302    
303      /**
304       * @return Percentage of progress in maps 
305       */
306      public synchronized float getMapProgress() { return mapProgress; }
307        
308      /**
309       * @return Percentage of progress in cleanup 
310       */
311      public synchronized float getCleanupProgress() { return cleanupProgress; }
312        
313      /**
314       * @return Percentage of progress in setup 
315       */
316      public synchronized float getSetupProgress() { return setupProgress; }
317        
318      /**
319       * @return Percentage of progress in reduce 
320       */
321      public synchronized float getReduceProgress() { return reduceProgress; }
322        
323      /**
324       * @return running state of the job
325       */
326      public synchronized State getState() { return runState; }
327        
328      /**
329       * @return start time of the job
330       */
331      synchronized public long getStartTime() { return startTime;}
332    
333      @Override
334      public Object clone() {
335        try {
336          return super.clone();
337        } catch (CloneNotSupportedException cnse) {
338          // Shouldn't happen since we do implement Clonable
339          throw new InternalError(cnse.toString());
340        }
341      }
342      
343      /**
344       * @return The jobid of the Job
345       */
346      public JobID getJobID() { return jobid; }
347        
348      /**
349       * @return the username of the job
350       */
351      public synchronized String getUsername() { return this.user;}
352      
353      /**
354       * Gets the Scheduling information associated to a particular Job.
355       * @return the scheduling information of the job
356       */
357      public synchronized String getSchedulingInfo() {
358       return schedulingInfo;
359      }
360    
361      /**
362       * Get the job acls.
363       * 
364       * @return a {@link Map} from {@link JobACL} to {@link AccessControlList}
365       */
366      public synchronized Map<JobACL, AccessControlList> getJobACLs() {
367        return jobACLs;
368      }
369    
370      /**
371       * Return the priority of the job
372       * @return job priority
373       */
374       public synchronized JobPriority getPriority() { return priority; }
375      
376       /**
377        * Gets any available info on the reason of failure of the job.
378        * @return diagnostic information on why a job might have failed.
379        */
380       public synchronized String getFailureInfo() {
381         return this.failureInfo;
382       }
383    
384    
385      /**
386       * Returns true if the status is for a completed job.
387       */
388      public synchronized boolean isJobComplete() {
389        return (runState == JobStatus.State.SUCCEEDED || 
390                runState == JobStatus.State.FAILED || 
391                runState == JobStatus.State.KILLED);
392      }
393    
394      ///////////////////////////////////////
395      // Writable
396      ///////////////////////////////////////
397      public synchronized void write(DataOutput out) throws IOException {
398        jobid.write(out);
399        out.writeFloat(setupProgress);
400        out.writeFloat(mapProgress);
401        out.writeFloat(reduceProgress);
402        out.writeFloat(cleanupProgress);
403        WritableUtils.writeEnum(out, runState);
404        out.writeLong(startTime);
405        Text.writeString(out, user);
406        WritableUtils.writeEnum(out, priority);
407        Text.writeString(out, schedulingInfo);
408        out.writeLong(finishTime);
409        out.writeBoolean(isRetired);
410        Text.writeString(out, historyFile);
411        Text.writeString(out, jobName);
412        Text.writeString(out, trackingUrl);
413        Text.writeString(out, jobFile);
414    
415        // Serialize the job's ACLs
416        out.writeInt(jobACLs.size());
417        for (Entry<JobACL, AccessControlList> entry : jobACLs.entrySet()) {
418          WritableUtils.writeEnum(out, entry.getKey());
419          entry.getValue().write(out);
420        }
421      }
422    
423      public synchronized void readFields(DataInput in) throws IOException {
424        this.jobid = new JobID();
425        this.jobid.readFields(in);
426        this.setupProgress = in.readFloat();
427        this.mapProgress = in.readFloat();
428        this.reduceProgress = in.readFloat();
429        this.cleanupProgress = in.readFloat();
430        this.runState = WritableUtils.readEnum(in, State.class);
431        this.startTime = in.readLong();
432        this.user = Text.readString(in);
433        this.priority = WritableUtils.readEnum(in, JobPriority.class);
434        this.schedulingInfo = Text.readString(in);
435        this.finishTime = in.readLong();
436        this.isRetired = in.readBoolean();
437        this.historyFile = Text.readString(in);
438        this.jobName = Text.readString(in);
439        this.trackingUrl = Text.readString(in);
440        this.jobFile = Text.readString(in);
441    
442        // De-serialize the job's ACLs
443        int numACLs = in.readInt();
444        for (int i = 0; i < numACLs; i++) {
445          JobACL aclType = WritableUtils.readEnum(in, JobACL.class);
446          AccessControlList acl = new AccessControlList(" ");
447          acl.readFields(in);
448          this.jobACLs.put(aclType, acl);
449        }
450      }
451    
452      /**
453       * Get the user-specified job name.
454       */
455      public String getJobName() {
456        return jobName;
457      }
458    
459      /**
460       * Get the configuration file for the job.
461       */
462      public String getJobFile() {
463        return jobFile;
464      }
465    
466      /**
467       * Get the link to the web-ui for details of the job.
468       */
469      public synchronized String getTrackingUrl() {
470        return trackingUrl;
471      }
472    
473      /**
474       * Get the finish time of the job.
475       */
476      public synchronized long getFinishTime() { 
477        return finishTime;
478      }
479    
480      /**
481       * Check whether the job has retired.
482       */
483      public synchronized boolean isRetired() {
484        return isRetired;
485      }
486    
487      /**
488       * @return the job history file name for a completed job. If job is not 
489       * completed or history file not available then return null.
490       */
491      public synchronized String getHistoryFile() {
492        return historyFile;
493      }
494    
495      /**
496       * @return number of used mapred slots
497       */
498      public int getNumUsedSlots() {
499        return numUsedSlots;
500      }
501    
502      /**
503       * @param n number of used mapred slots
504       */
505      public void setNumUsedSlots(int n) {
506        numUsedSlots = n;
507      }
508    
509      /**
510       * @return the number of reserved slots
511       */
512      public int getNumReservedSlots() {
513        return numReservedSlots;
514      }
515    
516      /**
517       * @param n the number of reserved slots
518       */
519      public void setNumReservedSlots(int n) {
520        this.numReservedSlots = n;
521      }
522    
523      /**
524       * @return the used memory
525       */
526      public int getUsedMem() {
527        return usedMem;
528      }
529    
530      /**
531       * @param m the used memory
532       */
533      public void setUsedMem(int m) {
534        this.usedMem = m;
535      }
536    
537      /**
538       * @return the reserved memory
539       */
540      public int getReservedMem() {
541        return reservedMem;
542     }
543    
544      /**
545       * @param r the reserved memory
546       */
547      public void setReservedMem(int r) {
548        this.reservedMem = r;
549      }
550    
551      /**
552       * @return the needed memory
553       */
554      public int getNeededMem() {
555      return neededMem;
556     }
557    
558      /**
559       * @param n the needed memory
560       */
561      public void setNeededMem(int n) {
562        this.neededMem = n;
563      }
564    
565      public String toString() {
566        StringBuffer buffer = new StringBuffer();
567        buffer.append("job-id : " + jobid);
568        buffer.append("map-progress : " + mapProgress);
569        buffer.append("reduce-progress : " + reduceProgress);
570        buffer.append("cleanup-progress : " + cleanupProgress);
571        buffer.append("setup-progress : " + setupProgress);
572        buffer.append("runstate : " + runState);
573        buffer.append("start-time : " + startTime);
574        buffer.append("user-name : " + user);
575        buffer.append("priority : " + priority);
576        buffer.append("scheduling-info : " + schedulingInfo);
577        buffer.append("num-used-slots" + numUsedSlots);
578        buffer.append("num-reserved-slots" + numReservedSlots);
579        buffer.append("used-mem" + usedMem);
580        buffer.append("reserved-mem" + reservedMem);
581        buffer.append("needed-mem" + neededMem);
582        return buffer.toString();
583      }
584    }