public final DataDependencyEvent getLastDataEventInfo(long timeThreshold) {
   for (int i = lastDataEvents.size() - 1; i >= 0; i--) {
     // walk back in time until we get first event that happened before the threshold
     DataDependencyEvent item = lastDataEvents.get(i);
     if (item.getTimestamp() < timeThreshold) {
       return item;
     }
   }
   return null;
 }
  TaskAttemptInfo(JSONObject jsonObject) throws JSONException {
    super(jsonObject);

    Preconditions.checkArgument(
        jsonObject
            .getString(Constants.ENTITY_TYPE)
            .equalsIgnoreCase(Constants.TEZ_TASK_ATTEMPT_ID));

    taskAttemptId = StringInterner.weakIntern(jsonObject.optString(Constants.ENTITY));

    // Parse additional Info
    final JSONObject otherInfoNode = jsonObject.getJSONObject(Constants.OTHER_INFO);
    startTime = otherInfoNode.optLong(Constants.START_TIME);
    endTime = otherInfoNode.optLong(Constants.FINISH_TIME);
    diagnostics = otherInfoNode.optString(Constants.DIAGNOSTICS);
    creationTime = otherInfoNode.optLong(Constants.CREATION_TIME);
    creationCausalTA =
        StringInterner.weakIntern(otherInfoNode.optString(Constants.CREATION_CAUSAL_ATTEMPT));
    allocationTime = otherInfoNode.optLong(Constants.ALLOCATION_TIME);
    containerId = StringInterner.weakIntern(otherInfoNode.optString(Constants.CONTAINER_ID));
    String id = otherInfoNode.optString(Constants.NODE_ID);
    nodeId = StringInterner.weakIntern((id != null) ? (id.split(":")[0]) : "");
    logUrl = otherInfoNode.optString(Constants.COMPLETED_LOGS_URL);

    status = StringInterner.weakIntern(otherInfoNode.optString(Constants.STATUS));
    container = new Container(containerId, nodeId);
    if (otherInfoNode.has(Constants.LAST_DATA_EVENTS)) {
      List<DataDependencyEvent> eventInfo =
          Utils.parseDataEventDependencyFromJSON(
              otherInfoNode.optJSONObject(Constants.LAST_DATA_EVENTS));
      long lastTime = 0;
      for (DataDependencyEvent item : eventInfo) {
        // check these are in time order
        Preconditions.checkState(lastTime < item.getTimestamp());
        lastTime = item.getTimestamp();
        lastDataEvents.add(item);
      }
    }
    terminationCause =
        StringInterner.weakIntern(otherInfoNode.optString(ATSConstants.TASK_ATTEMPT_ERROR_ENUM));
    executionTimeInterval = (endTime > startTime) ? (endTime - startTime) : 0;
  }