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    
019    package org.apache.hadoop.mapreduce;
020    
021    import java.io.DataInput;
022    import java.io.DataOutput;
023    import java.io.IOException;
024    
025    import org.apache.hadoop.classification.InterfaceAudience;
026    import org.apache.hadoop.classification.InterfaceStability;
027    
028    /**
029     * TaskAttemptID represents the immutable and unique identifier for 
030     * a task attempt. Each task attempt is one particular instance of a Map or
031     * Reduce Task identified by its TaskID. 
032     * 
033     * TaskAttemptID consists of 2 parts. First part is the 
034     * {@link TaskID}, that this TaskAttemptID belongs to.
035     * Second part is the task attempt number. <br> 
036     * An example TaskAttemptID is : 
037     * <code>attempt_200707121733_0003_m_000005_0</code> , which represents the
038     * zeroth task attempt for the fifth map task in the third job 
039     * running at the jobtracker started at <code>200707121733</code>.
040     * <p>
041     * Applications should never construct or parse TaskAttemptID strings
042     * , but rather use appropriate constructors or {@link #forName(String)} 
043     * method. 
044     * 
045     * @see JobID
046     * @see TaskID
047     */
048    @InterfaceAudience.Public
049    @InterfaceStability.Stable
050    public class TaskAttemptID extends org.apache.hadoop.mapred.ID {
051      protected static final String ATTEMPT = "attempt";
052      private TaskID taskId;
053      
054      /**
055       * Constructs a TaskAttemptID object from given {@link TaskID}.  
056       * @param taskId TaskID that this task belongs to  
057       * @param id the task attempt number
058       */
059      public TaskAttemptID(TaskID taskId, int id) {
060        super(id);
061        if(taskId == null) {
062          throw new IllegalArgumentException("taskId cannot be null");
063        }
064        this.taskId = taskId;
065      }
066      
067      /**
068       * Constructs a TaskId object from given parts.
069       * @param jtIdentifier jobTracker identifier
070       * @param jobId job number 
071       * @param type the TaskType 
072       * @param taskId taskId number
073       * @param id the task attempt number
074       */
075      public TaskAttemptID(String jtIdentifier, int jobId, TaskType type, 
076                           int taskId, int id) {
077        this(new TaskID(jtIdentifier, jobId, type, taskId), id);
078      }
079    
080      /**
081       * Constructs a TaskId object from given parts.
082       * @param jtIdentifier jobTracker identifier
083       * @param jobId job number
084       * @param isMap whether the tip is a map
085       * @param taskId taskId number
086       * @param id the task attempt number
087       */
088      @Deprecated
089      public TaskAttemptID(String jtIdentifier, int jobId, boolean isMap,
090                           int taskId, int id) {
091        this(new TaskID(jtIdentifier, jobId, isMap, taskId), id);
092      }
093      
094      public TaskAttemptID() { 
095        taskId = new TaskID();
096      }
097      
098      /** Returns the {@link JobID} object that this task attempt belongs to */
099      public JobID getJobID() {
100        return taskId.getJobID();
101      }
102      
103      /** Returns the {@link TaskID} object that this task attempt belongs to */
104      public TaskID getTaskID() {
105        return taskId;
106      }
107      
108      /**Returns whether this TaskID is a map ID */
109      @Deprecated
110      public boolean isMap() {
111        return taskId.isMap();
112      }
113        
114      /**Returns the TaskType of the TaskAttemptID */
115      public TaskType getTaskType() {
116        return taskId.getTaskType();
117      }
118      @Override
119      public boolean equals(Object o) {
120        if (!super.equals(o))
121          return false;
122    
123        TaskAttemptID that = (TaskAttemptID)o;
124        return this.taskId.equals(that.taskId);
125      }
126      
127      /**
128       * Add the unique string to the StringBuilder
129       * @param builder the builder to append ot
130       * @return the builder that was passed in.
131       */
132      protected StringBuilder appendTo(StringBuilder builder) {
133        return taskId.appendTo(builder).append(SEPARATOR).append(id);
134      }
135      
136      @Override
137      public void readFields(DataInput in) throws IOException {
138        super.readFields(in);
139        taskId.readFields(in);
140      }
141    
142      @Override
143      public void write(DataOutput out) throws IOException {
144        super.write(out);
145        taskId.write(out);
146      }
147    
148      @Override
149      public int hashCode() {
150        return taskId.hashCode() * 5 + id;
151      }
152      
153      /**Compare TaskIds by first tipIds, then by task numbers. */
154      @Override
155      public int compareTo(ID o) {
156        TaskAttemptID that = (TaskAttemptID)o;
157        int tipComp = this.taskId.compareTo(that.taskId);
158        if(tipComp == 0) {
159          return this.id - that.id;
160        }
161        else return tipComp;
162      }
163      @Override
164      public String toString() { 
165        return appendTo(new StringBuilder(ATTEMPT)).toString();
166      }
167    
168      /** Construct a TaskAttemptID object from given string 
169       * @return constructed TaskAttemptID object or null if the given String is null
170       * @throws IllegalArgumentException if the given string is malformed
171       */
172      public static TaskAttemptID forName(String str
173                                          ) throws IllegalArgumentException {
174        if(str == null)
175          return null;
176        String exceptionMsg = null;
177        try {
178          String[] parts = str.split(Character.toString(SEPARATOR));
179          if(parts.length == 6) {
180            if(parts[0].equals(ATTEMPT)) {
181              String type = parts[3];
182              TaskType t = TaskID.getTaskType(type.charAt(0));
183              if(t != null) {
184                return new org.apache.hadoop.mapred.TaskAttemptID
185                (parts[1],
186                 Integer.parseInt(parts[2]),
187                 t, Integer.parseInt(parts[4]), 
188                 Integer.parseInt(parts[5]));  
189              } else
190                exceptionMsg = "Bad TaskType identifier. TaskAttemptId string : "
191                    + str + " is not properly formed.";
192            }
193          }
194        } catch (Exception ex) {
195          //fall below
196        }
197        if (exceptionMsg == null) {
198          exceptionMsg = "TaskAttemptId string : " + str
199              + " is not properly formed";
200        }
201        throw new IllegalArgumentException(exceptionMsg);
202      }
203    
204    }