/*
   * (non-Javadoc)
   *
   * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools .tmf.event.TmfTimestamp)
   */
  @Override
  public synchronized TmfExperimentContext seekEvent(TmfTimestamp timestamp) {

    //		Tracer.trace("Ctx: seekEvent(TS) - start");

    if (timestamp == null) {
      timestamp = TmfTimestamp.BigBang;
    }

    // First, find the right checkpoint
    int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));

    // In the very likely case that the checkpoint was not found, bsearch
    // returns its negated would-be location (not an offset...). From that
    // index, we can then position the stream and get the event.
    if (index < 0) {
      index = Math.max(0, -(index + 2));
    }

    // Position the experiment at the checkpoint
    ITmfLocation<?> location;
    synchronized (fCheckpoints) {
      if (fCheckpoints.size() > 0) {
        if (index >= fCheckpoints.size()) {
          index = fCheckpoints.size() - 1;
        }
        location = fCheckpoints.elementAt(index).getLocation();
      } else {
        location = null;
      }
    }

    TmfExperimentContext context = seekLocation(location);
    context.setRank((long) index * fIndexPageSize);

    // And locate the event
    TmfEvent event = parseEvent(context);
    while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
      getNextEvent(context);
      event = parseEvent(context);
    }

    if (event == null) {
      context.setLocation(null);
      context.setRank(ITmfContext.UNKNOWN_RANK);
    }

    return context;
  }
  // Returns a brand new context based on the location provided
  // and initializes the event queues
  @Override
  public synchronized TmfExperimentContext seekLocation(ITmfLocation<?> location) {
    // Validate the location
    if (location != null && !(location instanceof TmfExperimentLocation)) {
      return null; // Throw an exception?
    }

    if (fTraces == null) { // experiment has been disposed
      return null;
    }

    // Instantiate the location
    TmfExperimentLocation expLocation =
        (location == null)
            ? new TmfExperimentLocation(
                new TmfLocationArray(new ITmfLocation<?>[fTraces.length]), new long[fTraces.length])
            : (TmfExperimentLocation) location.clone();

    // Create and populate the context's traces contexts
    TmfExperimentContext context =
        new TmfExperimentContext(fTraces, new TmfContext[fTraces.length]);
    //		Tracer.trace("Ctx: SeekLocation - start");

    long rank = 0;
    for (int i = 0; i < fTraces.length; i++) {
      // Get the relevant trace attributes
      ITmfLocation<?> traceLocation = expLocation.getLocation().locations[i];
      long traceRank = expLocation.getRanks()[i];

      // Set the corresponding sub-context
      context.getContexts()[i] = fTraces[i].seekLocation(traceLocation);
      context.getContexts()[i].setRank(traceRank);
      rank += traceRank;

      // Set the trace location and read the corresponding event
      expLocation.getLocation().locations[i] = context.getContexts()[i].getLocation();
      context.getEvents()[i] = fTraces[i].getNextEvent(context.getContexts()[i]);
    }

    //		Tracer.trace("Ctx: SeekLocation - done");

    // Finalize context
    context.setLocation(expLocation);
    context.setLastTrace(TmfExperimentContext.NO_TRACE);
    context.setRank(rank);

    fExperimentContext = context;

    return context;
  }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(long)
   */
  @Override
  public synchronized TmfExperimentContext seekEvent(long rank) {

    //		Tracer.trace("Ctx: seekEvent(rank) - start");

    // Position the stream at the previous checkpoint
    int index = (int) rank / fIndexPageSize;
    ITmfLocation<?> location;
    synchronized (fCheckpoints) {
      if (fCheckpoints.size() == 0) {
        location = null;
      } else {
        if (index >= fCheckpoints.size()) {
          index = fCheckpoints.size() - 1;
        }
        location = fCheckpoints.elementAt(index).getLocation();
      }
    }

    TmfExperimentContext context = seekLocation(location);
    context.setRank((long) index * fIndexPageSize);

    // And locate the event
    TmfEvent event = parseEvent(context);
    long pos = context.getRank();
    while (event != null && pos++ < rank) {
      getNextEvent(context);
      event = parseEvent(context);
    }

    if (event == null) {
      context.setLocation(null);
      context.setRank(ITmfContext.UNKNOWN_RANK);
    }

    return context;
  }