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