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 019package org.apache.hadoop.mapreduce; 020 021import java.io.DataInput; 022import java.io.DataOutput; 023import java.io.IOException; 024import java.text.NumberFormat; 025import java.util.EnumMap; 026import java.util.HashMap; 027import java.util.Map; 028import java.util.regex.Matcher; 029import java.util.regex.Pattern; 030 031import org.apache.hadoop.classification.InterfaceAudience; 032import org.apache.hadoop.classification.InterfaceStability; 033import org.apache.hadoop.io.WritableUtils; 034 035 036/** 037 * TaskID represents the immutable and unique identifier for 038 * a Map or Reduce Task. Each TaskID encompasses multiple attempts made to 039 * execute the Map or Reduce Task, each of which are uniquely indentified by 040 * their TaskAttemptID. 041 * 042 * TaskID consists of 3 parts. First part is the {@link JobID}, that this 043 * TaskInProgress belongs to. Second part of the TaskID is either 'm' or 'r' 044 * representing whether the task is a map task or a reduce task. 045 * And the third part is the task number. <br> 046 * An example TaskID is : 047 * <code>task_200707121733_0003_m_000005</code> , which represents the 048 * fifth map task in the third job running at the jobtracker 049 * started at <code>200707121733</code>. 050 * <p> 051 * Applications should never construct or parse TaskID strings 052 * , but rather use appropriate constructors or {@link #forName(String)} 053 * method. 054 * 055 * @see JobID 056 * @see TaskAttemptID 057 */ 058@InterfaceAudience.Public 059@InterfaceStability.Stable 060public class TaskID extends org.apache.hadoop.mapred.ID { 061 protected static final String TASK = "task"; 062 protected static final NumberFormat idFormat = NumberFormat.getInstance(); 063 public static final String TASK_ID_REGEX = TASK + "_(\\d+)_(\\d+)_" + 064 CharTaskTypeMaps.allTaskTypes + "_(\\d+)"; 065 public static final Pattern taskIdPattern = Pattern.compile(TASK_ID_REGEX); 066 067 static { 068 idFormat.setGroupingUsed(false); 069 idFormat.setMinimumIntegerDigits(6); 070 } 071 072 private JobID jobId; 073 private TaskType type; 074 075 /** 076 * Constructs a TaskID object from given {@link JobID}. 077 * 078 * @param jobId JobID that this tip belongs to 079 * @param type the {@link TaskType} of the task 080 * @param id the tip number 081 */ 082 public TaskID(JobID jobId, TaskType type, int id) { 083 super(id); 084 if(jobId == null) { 085 throw new IllegalArgumentException("jobId cannot be null"); 086 } 087 this.jobId = jobId; 088 this.type = type; 089 } 090 091 /** 092 * Constructs a TaskInProgressId object from given parts. 093 * 094 * @param jtIdentifier jobTracker identifier 095 * @param jobId job number 096 * @param type the TaskType 097 * @param id the tip number 098 */ 099 public TaskID(String jtIdentifier, int jobId, TaskType type, int id) { 100 this(new JobID(jtIdentifier, jobId), type, id); 101 } 102 103 /** 104 * Constructs a TaskID object from given {@link JobID}. 105 * 106 * @param jobId JobID that this tip belongs to 107 * @param isMap whether the tip is a map 108 * @param id the tip number 109 */ 110 @Deprecated 111 public TaskID(JobID jobId, boolean isMap, int id) { 112 this(jobId, isMap ? TaskType.MAP : TaskType.REDUCE, id); 113 } 114 115 /** 116 * Constructs a TaskInProgressId object from given parts. 117 * 118 * @param jtIdentifier jobTracker identifier 119 * @param jobId job number 120 * @param isMap whether the tip is a map 121 * @param id the tip number 122 */ 123 @Deprecated 124 public TaskID(String jtIdentifier, int jobId, boolean isMap, int id) { 125 this(new JobID(jtIdentifier, jobId), isMap, id); 126 } 127 128 /** 129 * Default constructor for Writable. Sets the task type to 130 * {@link TaskType#REDUCE}, the ID to 0, and the job ID to an empty job ID. 131 */ 132 public TaskID() { 133 this(new JobID(), TaskType.REDUCE, 0); 134 } 135 136 /** 137 * Returns the {@link JobID} object that this tip belongs to. 138 * 139 * @return the JobID object 140 */ 141 public JobID getJobID() { 142 return jobId; 143 } 144 145 /** 146 * Returns whether this TaskID is a map ID. 147 * 148 * @return whether this TaskID is a map ID 149 */ 150 @Deprecated 151 public boolean isMap() { 152 return type == TaskType.MAP; 153 } 154 155 /** 156 * Get the type of the task. 157 * 158 * @return the type of the task 159 */ 160 public TaskType getTaskType() { 161 return type; 162 } 163 164 @Override 165 public boolean equals(Object o) { 166 if (!super.equals(o)) 167 return false; 168 169 TaskID that = (TaskID)o; 170 return this.type == that.type && this.jobId.equals(that.jobId); 171 } 172 173 /** 174 * Compare TaskInProgressIds by first jobIds, then by tip numbers. 175 * Reducers are defined as greater than mappers. 176 * 177 * @param o the TaskID against which to compare 178 * @return 0 if equal, positive if this TaskID is greater, and negative if 179 * this TaskID is less 180 */ 181 @Override 182 public int compareTo(ID o) { 183 TaskID that = (TaskID)o; 184 int jobComp = this.jobId.compareTo(that.jobId); 185 if(jobComp == 0) { 186 if(this.type == that.type) { 187 return this.id - that.id; 188 } 189 else { 190 return this.type.compareTo(that.type); 191 } 192 } 193 else return jobComp; 194 } 195 @Override 196 public String toString() { 197 return appendTo(new StringBuilder(TASK)).toString(); 198 } 199 200 /** 201 * Add the unique string to the given builder. 202 * 203 * @param builder the builder to append to 204 * @return the builder that was passed in 205 */ 206 protected StringBuilder appendTo(StringBuilder builder) { 207 return jobId.appendTo(builder). 208 append(SEPARATOR). 209 append(CharTaskTypeMaps.getRepresentingCharacter(type)). 210 append(SEPARATOR). 211 append(idFormat.format(id)); 212 } 213 214 @Override 215 public int hashCode() { 216 return jobId.hashCode() * 524287 + id; 217 } 218 219 @Override 220 public void readFields(DataInput in) throws IOException { 221 super.readFields(in); 222 jobId.readFields(in); 223 type = WritableUtils.readEnum(in, TaskType.class); 224 } 225 226 @Override 227 public void write(DataOutput out) throws IOException { 228 super.write(out); 229 jobId.write(out); 230 WritableUtils.writeEnum(out, type); 231 } 232 233 /** 234 * Construct a TaskID object from given string. 235 * 236 * @param str the target string 237 * @return constructed TaskID object or null if the given String is null 238 * @throws IllegalArgumentException if the given string is malformed 239 */ 240 public static TaskID forName(String str) 241 throws IllegalArgumentException { 242 if(str == null) 243 return null; 244 Matcher m = taskIdPattern.matcher(str); 245 if (m.matches()) { 246 return new org.apache.hadoop.mapred.TaskID(m.group(1), 247 Integer.parseInt(m.group(2)), 248 CharTaskTypeMaps.getTaskType(m.group(3).charAt(0)), 249 Integer.parseInt(m.group(4))); 250 } 251 String exceptionMsg = "TaskId string : " + str + " is not properly formed" + 252 "\nReason: " + m.toString(); 253 throw new IllegalArgumentException(exceptionMsg); 254 } 255 /** 256 * Gets the character representing the {@link TaskType}. 257 * 258 * @param type the TaskType 259 * @return the character 260 */ 261 public static char getRepresentingCharacter(TaskType type) { 262 return CharTaskTypeMaps.getRepresentingCharacter(type); 263 } 264 /** 265 * Gets the {@link TaskType} corresponding to the character. 266 * 267 * @param c the character 268 * @return the TaskType 269 */ 270 public static TaskType getTaskType(char c) { 271 return CharTaskTypeMaps.getTaskType(c); 272 } 273 274 /** 275 * Returns a string of characters describing all possible {@link TaskType} 276 * values 277 * 278 * @return a string of all task type characters 279 */ 280 public static String getAllTaskTypes() { 281 return CharTaskTypeMaps.allTaskTypes; 282 } 283 284 /** 285 * Maintains the mapping from the character representation of a task type to 286 * the enum class TaskType constants 287 */ 288 static class CharTaskTypeMaps { 289 private static EnumMap<TaskType, Character> typeToCharMap = 290 new EnumMap<TaskType,Character>(TaskType.class); 291 private static Map<Character, TaskType> charToTypeMap = 292 new HashMap<Character, TaskType>(); 293 static String allTaskTypes = "(m|r|s|c|t)"; 294 static { 295 setupTaskTypeToCharMapping(); 296 setupCharToTaskTypeMapping(); 297 } 298 299 private static void setupTaskTypeToCharMapping() { 300 typeToCharMap.put(TaskType.MAP, 'm'); 301 typeToCharMap.put(TaskType.REDUCE, 'r'); 302 typeToCharMap.put(TaskType.JOB_SETUP, 's'); 303 typeToCharMap.put(TaskType.JOB_CLEANUP, 'c'); 304 typeToCharMap.put(TaskType.TASK_CLEANUP, 't'); 305 } 306 307 private static void setupCharToTaskTypeMapping() { 308 charToTypeMap.put('m', TaskType.MAP); 309 charToTypeMap.put('r', TaskType.REDUCE); 310 charToTypeMap.put('s', TaskType.JOB_SETUP); 311 charToTypeMap.put('c', TaskType.JOB_CLEANUP); 312 charToTypeMap.put('t', TaskType.TASK_CLEANUP); 313 } 314 315 static char getRepresentingCharacter(TaskType type) { 316 return typeToCharMap.get(type); 317 } 318 static TaskType getTaskType(char c) { 319 return charToTypeMap.get(c); 320 } 321 } 322 323}