/** Update the global time range */
  protected void updateTimeRange() {
    TmfTimestamp startTime =
        fTimeRange != TmfTimeRange.Null ? fTimeRange.getStartTime() : TmfTimestamp.BigCrunch;
    TmfTimestamp endTime =
        fTimeRange != TmfTimeRange.Null ? fTimeRange.getEndTime() : TmfTimestamp.BigBang;

    for (ITmfTrace<T> trace : fTraces) {
      TmfTimestamp traceStartTime = trace.getStartTime();
      if (traceStartTime.compareTo(startTime, true) < 0) startTime = traceStartTime;
      TmfTimestamp traceEndTime = trace.getEndTime();
      if (traceEndTime.compareTo(endTime, true) > 0) endTime = traceEndTime;
    }
    fTimeRange = new TmfTimeRange(startTime, endTime);
  }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#parseEvent(org.eclipse.linuxtools .tmf.trace.TmfContext)
   */
  @Override
  public TmfEvent parseEvent(TmfContext context) {

    // Validate the context
    if (!(context instanceof TmfExperimentContext)) {
      return null; // Throw an exception?
    }

    if (!context.equals(fExperimentContext)) {
      //    		Tracer.trace("Ctx: Restoring context");
      seekLocation(context.getLocation());
    }

    TmfExperimentContext expContext = (TmfExperimentContext) context;

    // If an event was consumed previously, get the next one from that trace
    int lastTrace = expContext.getLastTrace();
    if (lastTrace != TmfExperimentContext.NO_TRACE) {
      TmfContext traceContext = expContext.getContexts()[lastTrace];
      expContext.getEvents()[lastTrace] =
          expContext.getTraces()[lastTrace].getNextEvent(traceContext);
      expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
      fExperimentContext = (TmfExperimentContext) context;
    }

    // Scan the candidate events and identify the "next" trace to read from
    int trace = TmfExperimentContext.NO_TRACE;
    TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
    for (int i = 0; i < expContext.getTraces().length; i++) {
      TmfEvent event = expContext.getEvents()[i];
      if (event != null && event.getTimestamp() != null) {
        TmfTimestamp otherTS = event.getTimestamp();
        if (otherTS.compareTo(timestamp, true) < 0) {
          trace = i;
          timestamp = otherTS;
        }
      }
    }

    TmfEvent event = null;
    if (trace != TmfExperimentContext.NO_TRACE) {
      event = expContext.getEvents()[trace];
    }

    return event;
  }
 public synchronized void updateIndex(ITmfContext context, TmfTimestamp timestamp) {
   // Build the index as we go along
   long rank = context.getRank();
   if (context.isValidRank() && (rank % fIndexPageSize) == 0) {
     // Determine the table position
     long position = rank / fIndexPageSize;
     // Add new entry at proper location (if empty)
     if (fCheckpoints.size() == position) {
       ITmfLocation<?> location = context.getLocation().clone();
       fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
       //                System.out.println(this + "[" + (fCheckpoints.size() - 1) + "] " +
       // timestamp + ", "
       //                        + location.toString());
     }
   }
 }
  @Override
  public synchronized TmfEvent getNextEvent(TmfContext context) {

    // Validate the context
    if (!(context instanceof TmfExperimentContext)) {
      return null; // Throw an exception?
    }

    if (!context.equals(fExperimentContext)) {
      //    		Tracer.trace("Ctx: Restoring context");
      fExperimentContext = seekLocation(context.getLocation());
    }

    TmfExperimentContext expContext = (TmfExperimentContext) context;

    //		dumpContext(expContext, true);

    // If an event was consumed previously, get the next one from that trace
    int lastTrace = expContext.getLastTrace();
    if (lastTrace != TmfExperimentContext.NO_TRACE) {
      TmfContext traceContext = expContext.getContexts()[lastTrace];
      expContext.getEvents()[lastTrace] =
          expContext.getTraces()[lastTrace].getNextEvent(traceContext);
      expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
    }

    // Scan the candidate events and identify the "next" trace to read from
    TmfEvent eventArray[] = expContext.getEvents();
    if (eventArray == null) {
      return null;
    }
    int trace = TmfExperimentContext.NO_TRACE;
    TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
    if (eventArray.length == 1) {
      if (eventArray[0] != null) {
        timestamp = eventArray[0].getTimestamp();
        trace = 0;
      }
    } else {
      for (int i = 0; i < eventArray.length; i++) {
        TmfEvent event = eventArray[i];
        if (event != null && event.getTimestamp() != null) {
          TmfTimestamp otherTS = event.getTimestamp();
          if (otherTS.compareTo(timestamp, true) < 0) {
            trace = i;
            timestamp = otherTS;
          }
        }
      }
    }
    // Update the experiment context and set the "next" event
    TmfEvent event = null;
    if (trace != TmfExperimentContext.NO_TRACE) {
      updateIndex(expContext, timestamp);

      TmfContext traceContext = expContext.getContexts()[trace];
      TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation();
      //	        expLocation.getLocation()[trace] = traceContext.getLocation().clone();
      expLocation.getLocation().locations[trace] = traceContext.getLocation();

      //	        updateIndex(expContext, timestamp);

      expLocation.getRanks()[trace] = traceContext.getRank();
      expContext.setLastTrace(trace);
      expContext.updateRank(1);
      event = expContext.getEvents()[trace];
      fExperimentContext = expContext;
    }

    //		if (event != null) {
    //    		Tracer.trace("Exp: " + (expContext.getRank() - 1) + ": " +
    // event.getTimestamp().toString());
    //    		dumpContext(expContext, false);
    //    		Tracer.trace("Ctx: Event returned= " + event.getTimestamp().toString());
    //		}

    return event;
  }