code: public TaskAttemptInfo getTaskAttemptInfo(TaskType taskType, int taskNumber,
        int taskAttemptNumber) {
      // does not care about locality. assume default locality is NODE_LOCAL.
      // But if both task and task attempt exist in trace, use logged locality.
      int locality = 0;
      LoggedTask loggedTask = getLoggedTask(taskType, taskNumber);
      if (loggedTask == null) {
        // TODO insert parameters
        TaskInfo taskInfo = new TaskInfo(0, 0, 0, 0, 0);
        return makeUpTaskAttemptInfo(taskType, taskInfo, taskAttemptNumber,
            taskNumber, locality);
      }
  
      LoggedTaskAttempt loggedAttempt = getLoggedTaskAttempt(taskType,
          taskNumber, taskAttemptNumber);
      if (loggedAttempt == null) {
        // Task exists, but attempt is missing.
        TaskInfo taskInfo = getTaskInfo(loggedTask);
        return makeUpTaskAttemptInfo(taskType, taskInfo, taskAttemptNumber,
            taskNumber, locality);
      } else {
        // TODO should we handle killed attempts later?
        if (loggedAttempt.getResult()== Values.KILLED) {
          TaskInfo taskInfo = getTaskInfo(loggedTask);
          return makeUpTaskAttemptInfo(taskType, taskInfo, taskAttemptNumber,
              taskNumber, locality);
        } else {
          return getTaskAttemptInfo(loggedTask, loggedAttempt);
        }
      }
    }
docs: Get a {@link TaskAttemptInfo} with a {@link TaskAttemptID} associated with
  taskType, taskNumber, and taskAttemptNumber. This function does not care
  about locality, and follows the following decision logic: 1. Make up a
  {@link TaskAttemptInfo} if the task attempt is missing in trace, 2. Make up
  a {@link TaskAttemptInfo} if the task attempt has a KILLED final status in
  trace, 3. Otherwise (final state is SUCCEEDED or FAILED), construct the
  {@link TaskAttemptInfo} from the trace.