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 */
018package org.apache.hadoop.mapreduce;
019
020import java.io.DataInput;
021import java.io.DataOutput;
022import java.io.IOException;
023import java.util.HashMap;
024import java.util.Map;
025import java.util.Map.Entry;
026
027import org.apache.hadoop.classification.InterfaceAudience;
028import org.apache.hadoop.classification.InterfaceStability;
029import org.apache.hadoop.io.Text;
030import org.apache.hadoop.io.Writable;
031import org.apache.hadoop.io.WritableFactories;
032import org.apache.hadoop.io.WritableFactory;
033import org.apache.hadoop.io.WritableUtils;
034import org.apache.hadoop.security.authorize.AccessControlList;
035import org.apache.hadoop.util.StringInterner;
036
037/**************************************************
038 * Describes the current status of a job.
039 **************************************************/
040@InterfaceAudience.Public
041@InterfaceStability.Evolving
042public 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}