@Override
 public void handleData(final ITmfEvent event) {
   super.handleData(event);
   if (event.getTrace() == trace) {
     sci.processEvent(event);
   }
 }
  /**
   * Constructor
   *
   * @param ssid The state system's ID
   * @param partialInput The state change input object that was used to build the upstream state
   *     system. This partial history will make its own copy (since they have different targets).
   * @param pss The partial history's inner state system. It should already be assigned to
   *     partialInput.
   * @param realBackend The real state history back-end to use. It's supposed to be modular, so it
   *     should be able to be of any type.
   * @param granularity Configuration parameter indicating how many trace events there should be
   *     between each checkpoint
   */
  public PartialHistoryBackend(
      @NonNull String ssid,
      ITmfStateProvider partialInput,
      PartialStateSystem pss,
      IStateHistoryBackend realBackend,
      long granularity) {
    if (granularity <= 0
        || partialInput == null
        || pss == null
        || partialInput.getAssignedStateSystem() != pss) {
      throw new IllegalArgumentException();
    }

    final long startTime = realBackend.getStartTime();

    fSSID = ssid;
    fPartialInput = partialInput;
    fPartialSS = pss;

    fInnerHistory = realBackend;
    fGranularity = granularity;

    fLatestTime = startTime;

    registerCheckpoints();
  }
    public CheckpointsRequest(ITmfStateProvider input, Map<Long, Long> checkpoints) {
      super(
          ITmfEvent.class,
          TmfTimeRange.ETERNITY,
          0,
          ITmfEventRequest.ALL_DATA,
          ITmfEventRequest.ExecutionType.FOREGROUND);
      checkpoints.clear();
      this.trace = input.getTrace();
      this.checkpts = checkpoints;
      eventCount = 0;
      lastCheckpointAt = 0;

      /* Insert a checkpoint at the start of the trace */
      checkpoints.put(input.getStartTime(), 0L);
    }
 PartialStateSystemRequest(ITmfStateProvider sci, TmfTimeRange range) {
   super(
       ITmfEvent.class,
       range,
       0,
       ITmfEventRequest.ALL_DATA,
       ITmfEventRequest.ExecutionType.BACKGROUND);
   this.sci = sci;
   this.trace = sci.getTrace();
 }
  @Override
  public void doQuery(List<@Nullable ITmfStateInterval> currentStateInfo, long t)
      throws TimeRangeException, StateSystemDisposedException {
    /* Wait for required steps to be done */
    waitForCheckpoints();
    fPartialSS.getUpstreamSS().waitUntilBuilt();

    if (!checkValidTime(t)) {
      throw new TimeRangeException(
          fSSID
              + " Time:"
              + t
              + ", Start:"
              + getStartTime()
              + ", End:"
              + getEndTime()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }

    /* Reload the previous checkpoint */
    long checkpointTime = fCheckpoints.floorKey(t);
    fInnerHistory.doQuery(currentStateInfo, checkpointTime);

    /*
     * Set the initial contents of the partial state system (which is the
     * contents of the query at the checkpoint).
     */
    List<@NonNull ITmfStateInterval> filledStateInfo =
        checkNotNullContents(currentStateInfo.stream()).collect(Collectors.toList());

    fPartialSS.takeQueryLock();
    fPartialSS.replaceOngoingState(filledStateInfo);

    /* Send an event request to update the state system to the target time. */
    TmfTimeRange range =
        new TmfTimeRange(
            /*
             * The state at the checkpoint already includes any state change
             * caused by the event(s) happening exactly at 'checkpointTime',
             * if any. We must not include those events in the query.
             */
            TmfTimestamp.fromNanos(checkpointTime + 1), TmfTimestamp.fromNanos(t));
    ITmfEventRequest request = new PartialStateSystemRequest(fPartialInput, range);
    fPartialInput.getTrace().sendRequest(request);

    try {
      request.waitForCompletion();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    /*
     * Now the partial state system should have the ongoing time we are
     * looking for. However, the method expects a List of *state intervals*,
     * not state values, so we'll create intervals with a dummy end time.
     */
    for (int i = 0; i < currentStateInfo.size(); i++) {
      long start = 0;
      start = ((ITmfStateSystem) fPartialSS).getOngoingStartTime(i);
      ITmfStateValue val = ((ITmfStateSystem) fPartialSS).queryOngoingState(i);

      ITmfStateInterval interval = new TmfStateInterval(start, t, i, checkNotNull(val));
      currentStateInfo.set(i, interval);
    }

    fPartialSS.releaseQueryLock();
  }
 @Override
 public void dispose() {
   fPartialInput.dispose();
   fPartialSS.dispose();
   fInnerHistory.dispose();
 }
 private void registerCheckpoints() {
   ITmfEventRequest request = new CheckpointsRequest(fPartialInput, fCheckpoints);
   fPartialInput.getTrace().sendRequest(request);
   /* The request will countDown the checkpoints latch once it's finished */
 }