Rename xxx.lttng to xxx.lttng.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / experiment / TmfExperiment.java
index 52b1cd291ec481dafdb902563b8d7f989fd64110..82fcf996fac9731b8fe91993d70673e9e68e137a 100644 (file)
 
 package org.eclipse.linuxtools.tmf.experiment;
 
+import java.io.FileNotFoundException;
 import java.util.Collections;
 import java.util.Vector;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.linuxtools.tmf.component.TmfProvider;
+import org.eclipse.linuxtools.tmf.component.TmfEventProvider;
 import org.eclipse.linuxtools.tmf.event.TmfEvent;
 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.request.ITmfDataRequest;
+import org.eclipse.linuxtools.tmf.request.ITmfEventRequest;
 import org.eclipse.linuxtools.tmf.request.TmfDataRequest;
 import org.eclipse.linuxtools.tmf.request.TmfEventRequest;
-import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentDisposedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentRangeUpdatedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal;
 import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalManager;
+import org.eclipse.linuxtools.tmf.signal.TmfTraceUpdatedSignal;
 import org.eclipse.linuxtools.tmf.trace.ITmfContext;
 import org.eclipse.linuxtools.tmf.trace.ITmfLocation;
 import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
 import org.eclipse.linuxtools.tmf.trace.TmfCheckpoint;
 import org.eclipse.linuxtools.tmf.trace.TmfContext;
-import org.eclipse.linuxtools.tmf.trace.TmfTraceUpdatedSignal;
 
 /**
  * <b><u>TmfExperiment</u></b>
  * <p>
- * TmfExperiment presents a time-ordered, unified view of a set of TmfTraces
- * that are part of a tracing experiment. 
+ * TmfExperiment presents a time-ordered, unified view of a set of TmfTraces that are part of a tracing experiment.
  * <p>
  */
-public class TmfExperiment<T extends TmfEvent> extends TmfProvider<T> implements ITmfTrace {
+public class TmfExperiment<T extends TmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T> {
 
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
 
-       // The currently selected experiment
-    private static TmfExperiment<?> fCurrentExperiment;
-
-       // The experiment ID
-    private String fExperimentId;
+    // The currently selected experiment
+    protected static TmfExperiment<?> fCurrentExperiment = null;
 
     // The set of traces that constitute the experiment
-    private ITmfTrace[] fTraces;
+    protected ITmfTrace<T>[] fTraces;
 
     // The total number of events
-    private long fNbEvents;
+    protected long fNbEvents;
 
     // The experiment time range
-    private TmfTimeRange fTimeRange;
+    protected TmfTimeRange fTimeRange;
+
+    // The experiment reference timestamp (default: Zero)
+    protected TmfTimestamp fEpoch;
 
-    // The experiment reference timestamp (default: BigBang)
-    private TmfTimestamp fEpoch;
+    // The experiment index
+    protected Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
 
-       // The experiment index
-       private Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
+    // The current experiment context
+    protected TmfExperimentContext fExperimentContext;
 
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
 
+    @Override
+    public boolean validate(IProject project, String path) {
+        return true;
+    }
+
+    @Override
+    public void initTrace(String path, Class<T> eventType) throws FileNotFoundException {
+    }
+
+    @Override
+    public void initTrace(String path, Class<T> eventType, boolean indexTrace) throws FileNotFoundException {
+    }
+
+    @Override
+    public void initTrace(String path, Class<T> eventType, int cacheSize) throws FileNotFoundException {
+    }
+
+    @Override
+    public void initTrace(String path, Class<T> eventType, int cacheSize, boolean indexTrace) throws FileNotFoundException {
+    }
+
     /**
      * @param type
      * @param id
@@ -79,16 +107,27 @@ public class TmfExperiment<T extends TmfEvent> extends TmfProvider<T> implements
      * @param epoch
      * @param indexPageSize
      */
-    public TmfExperiment(Class<T> type, String id, ITmfTrace[] traces, TmfTimestamp epoch, int indexPageSize) {
-       super(type);
+    public TmfExperiment(Class<T> type, String id, ITmfTrace<T>[] traces, TmfTimestamp epoch, int indexPageSize) {
+        this(type, id, traces, TmfTimestamp.Zero, indexPageSize, false);
+    }
+
+    public TmfExperiment(Class<T> type, String id, ITmfTrace<T>[] traces, TmfTimestamp epoch, int indexPageSize, boolean preIndexExperiment) {
+        super(id, type);
+
+        fTraces = traces;
+        fEpoch = epoch;
+        fIndexPageSize = indexPageSize;
+        fTimeRange = TmfTimeRange.Null;
 
-       fExperimentId = id;
-       fTraces = traces;
-       fEpoch = epoch;
-       fIndexPageSize = indexPageSize;
+        if (preIndexExperiment) {
+            indexExperiment(true);
+            updateTimeRange();
+        }
+
+    }
 
-               updateNbEvents();
-               updateTimeRange();
+    protected TmfExperiment(String id, Class<T> type) {
+        super(id, type);
     }
 
     /**
@@ -96,7 +135,7 @@ public class TmfExperiment<T extends TmfEvent> extends TmfProvider<T> implements
      * @param id
      * @param traces
      */
-    public TmfExperiment(Class<T> type, String id, ITmfTrace[] traces) {
+    public TmfExperiment(Class<T> type, String id, ITmfTrace<T>[] traces) {
         this(type, id, traces, TmfTimestamp.Zero, DEFAULT_INDEX_PAGE_SIZE);
     }
 
@@ -106,212 +145,269 @@ public class TmfExperiment<T extends TmfEvent> extends TmfProvider<T> implements
      * @param traces
      * @param indexPageSize
      */
-    public TmfExperiment(Class<T> type, String id, ITmfTrace[] traces, int indexPageSize) {
+    public TmfExperiment(Class<T> type, String id, ITmfTrace<T>[] traces, int indexPageSize) {
         this(type, id, traces, TmfTimestamp.Zero, indexPageSize);
     }
 
     /**
+     * Copy constructor
      * 
+     * @param other
+     */
+    @SuppressWarnings("unchecked")
+    public TmfExperiment(TmfExperiment<T> other) {
+        super(other.getName() + "(clone)", other.fType); //$NON-NLS-1$
+
+        fEpoch = other.fEpoch;
+        fIndexPageSize = other.fIndexPageSize;
+
+        fTraces = new ITmfTrace[other.fTraces.length];
+        for (int trace = 0; trace < other.fTraces.length; trace++) {
+            fTraces[trace] = other.fTraces[trace].copy();
+        }
+
+        fNbEvents = other.fNbEvents;
+        fTimeRange = other.fTimeRange;
+    }
+
+    @Override
+    public TmfExperiment<T> copy() {
+        TmfExperiment<T> experiment = new TmfExperiment<T>(this);
+        TmfSignalManager.deregister(experiment);
+        return experiment;
+    }
+
+    /**
+     * Clears the experiment
      */
     @Override
-       public void deregister() {
-       fTraces = null;
-       fCheckpoints.clear();
-       fCurrentExperiment= null;
-        super.deregister();
+    @SuppressWarnings("rawtypes")
+    public synchronized void dispose() {
+
+        TmfExperimentDisposedSignal<T> signal = new TmfExperimentDisposedSignal<T>(this, this);
+        broadcast(signal);
+
+        if (fTraces != null) {
+            for (ITmfTrace trace : fTraces) {
+                trace.dispose();
+            }
+            fTraces = null;
+        }
+        if (fCheckpoints != null) {
+            fCheckpoints.clear();
+        }
+        super.dispose();
     }
 
     // ------------------------------------------------------------------------
-    // ITmfTrace accessors
+    // ITmfTrace
     // ------------------------------------------------------------------------
 
-       public String getPath() {
-               return null;
-       }
+    @Override
+    public long getNbEvents() {
+        return fNbEvents;
+    }
 
-       public String getName() {
-               return fExperimentId;
-       }
+    @Override
+    public int getCacheSize() {
+        return fIndexPageSize;
+    }
 
-       public long getNbEvents() {
-               return fNbEvents;
-       }
+    @Override
+    public TmfTimeRange getTimeRange() {
+        return fTimeRange;
+    }
 
-       public TmfTimeRange getTimeRange() {
-               return fTimeRange;
-       }
+    @Override
+    public TmfTimestamp getStartTime() {
+        return fTimeRange.getStartTime();
+    }
 
-       public TmfTimestamp getStartTime() {
-               return fTimeRange.getStartTime();
-       }
+    @Override
+    public TmfTimestamp getEndTime() {
+        return fTimeRange.getEndTime();
+    }
 
-       public TmfTimestamp getEndTime() {
-               return fTimeRange.getEndTime();
-       }
+    public Vector<TmfCheckpoint> getCheckpoints() {
+        return fCheckpoints;
+    }
 
     // ------------------------------------------------------------------------
     // Accessors
     // ------------------------------------------------------------------------
 
+    public static void setCurrentExperiment(TmfExperiment<?> experiment) {
+        fCurrentExperiment = experiment;
+    }
+
     public static TmfExperiment<?> getCurrentExperiment() {
-       return fCurrentExperiment;
+        return fCurrentExperiment;
     }
 
     public TmfTimestamp getEpoch() {
-       return fEpoch;
+        return fEpoch;
     }
 
-    public ITmfTrace[] getTraces() {
-       return fTraces;
+    public ITmfTrace<T>[] getTraces() {
+        return fTraces;
     }
 
     /**
-     * Returns the rank of the first event with the requested timestamp.
-     * If none, returns the index of the next event (if any).
-     *  
-     * @param ts
+     * Returns the rank of the first event with the requested timestamp. If none, returns the index of the next event
+     * (if any).
+     * 
+     * @param timestamp
      * @return
      */
-    public long getRank(TmfTimestamp ts) {
-        // FIXME: Go over all the traces
-       ITmfTrace trace = fTraces[0];
-       TmfContext context = trace.seekEvent(ts);
-       return context.getRank();
+    @Override
+    public long getRank(TmfTimestamp timestamp) {
+        TmfExperimentContext context = seekEvent(timestamp);
+        return context.getRank();
     }
 
     /**
-     * Returns the timestamp of the event at the requested index.
-     * If none, returns null.
-     *  
+     * Returns the timestamp of the event at the requested index. If none, returns null.
+     * 
      * @param index
      * @return
      */
     public TmfTimestamp getTimestamp(int index) {
-        // FIXME: Go over all the traces
-       ITmfTrace trace = fTraces[0];
-       TmfContext context = trace.seekEvent(index);
-       TmfEvent event = trace.getNextEvent(context);
-       TmfTimestamp timestamp = (event != null) ? event.getTimestamp() : null;
-       return timestamp;
+        TmfExperimentContext context = seekEvent(index);
+        TmfEvent event = getNextEvent(context);
+        return (event != null) ? event.getTimestamp() : null;
     }
 
     // ------------------------------------------------------------------------
     // Operators
     // ------------------------------------------------------------------------
 
-//    /**
-//     * Add a trace to the experiment trace set
-//     * 
-//     * @param trace
-//     */
-//    public void addTrace(ITmfTrace trace) {
-//             fTraces.add(trace);
-//             synchronized(this) {
-//                     updateNbEvents();
-//                     updateTimeRange();
-//             }
-//    }
-
-    /**
-     * Update the total number of events
-     */
-    private void updateNbEvents() {
-       int nbEvents = 0;
-       for (ITmfTrace trace : fTraces) {
-               nbEvents += trace.getNbEvents();
-       }
-       fNbEvents = nbEvents;
-    }
-
     /**
      * Update the global time range
      */
-    private void updateTimeRange() {
-               TmfTimestamp startTime = fTimeRange != null ? fTimeRange.getStartTime() : TmfTimestamp.BigCrunch;
-               TmfTimestamp endTime   = fTimeRange != null ? fTimeRange.getEndTime()   : TmfTimestamp.BigBang;
-
-               for (ITmfTrace 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);
+    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);
     }
 
     // ------------------------------------------------------------------------
     // TmfProvider
     // ------------------------------------------------------------------------
+    @Override
+    public ITmfContext armRequest(ITmfDataRequest<T> request) {
+//             Tracer.trace("Ctx: Arming request - start");
+        TmfTimestamp timestamp = (request instanceof ITmfEventRequest<?>) ? ((ITmfEventRequest<T>) request).getRange().getStartTime()
+                : null;
+
+        if (TmfTimestamp.BigBang.equals(timestamp) || request.getIndex() > 0) {
+            timestamp = null; // use request index
+        }
+
+        TmfExperimentContext context = null;
+        if (timestamp != null) {
+            // seek by timestamp
+            context = seekEvent(timestamp);
+            ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
+        } else {
+            // Seek by rank
+            if ((fExperimentContext != null) && fExperimentContext.getRank() == request.getIndex()) {
+                // We are already at the right context -> no need to seek
+                context = fExperimentContext;
+            } else {
+                context = seekEvent(request.getIndex());
+            }
+        }
+//             Tracer.trace("Ctx: Arming request - done");
+        return context;
+    }
 
-       @Override
-       public ITmfContext setContext(TmfDataRequest<T> request) {
-               TmfTimestamp timestamp = (request instanceof TmfEventRequest<?>) ?
-                       ((TmfEventRequest<T>) request).getRange().getStartTime() : null;
-
-               TmfExperimentContext context = (timestamp != null) ? 
-                       seekEvent(timestamp) : seekEvent(request.getIndex());
-
-               return context;
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public T getNext(ITmfContext context) {
-               if (context instanceof TmfExperimentContext) {
-                       return (T) getNextEvent((TmfExperimentContext) context);
-               }
-               return null;
-       }
-
-       @Override
-       public boolean isCompleted(TmfDataRequest<T> request, T data) {
-               if (request instanceof TmfEventRequest<?> && data != null) {
-                       return data.getTimestamp().compareTo(((TmfEventRequest<T>) request).getRange().getEndTime(), false) > 0;
-               }
-               return false;
-       }
+    @SuppressWarnings("unchecked")
+    @Override
+    public T getNext(ITmfContext context) {
+        if (context instanceof TmfExperimentContext) {
+            return (T) getNextEvent((TmfExperimentContext) context);
+        }
+        return null;
+    }
 
     // ------------------------------------------------------------------------
     // ITmfTrace trace positioning
     // ------------------------------------------------------------------------
 
-       // Returns a brand new context based on the location provided
-       // Arms the event queues
-       // NOTE: This is a fine example of pathological coupling...
-       public TmfExperimentContext seekLocation(ITmfLocation location) {
-               if (location instanceof TmfExperimentLocation || location == null) {
-                       ITmfLocation[] oldloc = (location != null) ? ((TmfExperimentLocation) location).getLocations() : new TmfExperimentLocation[fTraces.length];
-                       ITmfLocation[] newloc = new ITmfLocation[fTraces.length];
-                       TmfContext[] contexts = new TmfContext[fTraces.length];
-
-                       TmfExperimentContext context = new TmfExperimentContext(fTraces, contexts);
-                       TmfEvent[] events = context.getEvents();
-
-                       long rank = 0;
-                       for (int i = 0; i < fTraces.length; i++) {
-                               contexts[i] = fTraces[i].seekLocation(oldloc[i]);
-                               newloc[i]   = contexts[i].getLocation();        // No clone here
-                               events[i]   = fTraces[i].parseEvent(contexts[i]);
-                               rank += contexts[i].getRank();
-                       }
-                       context.setLocation(new TmfExperimentLocation(newloc));
-                       context.setRank(rank);
-                       return context;
-               }
-               return null;
-       }
-
-       public TmfExperimentContext seekEvent(TmfTimestamp timestamp) {
-
-               if (timestamp == null) {
-               timestamp = TmfTimestamp.BigBang;
-       }
-
-       // First, find the right checkpoint
-       int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
+    // 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(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
@@ -321,391 +417,484 @@ public class TmfExperiment<T extends TmfEvent> extends TmfProvider<T> implements
         }
 
         // Position the experiment at the checkpoint
-        ITmfLocation location;
+        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 nextEventContext = seekLocation(location);
-        nextEventContext.setRank(index * fIndexPageSize);
-        TmfExperimentContext currentEventContext = new TmfExperimentContext(nextEventContext);
-
-        // And get the event
-        TmfEvent event = getNextEvent(nextEventContext);
+            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) {
-            currentEventContext = new TmfExperimentContext(nextEventContext);
-//             currentEventContext.setLocation(nextEventContext.getLocation());
-//             currentEventContext.updateRank(1);
-               event = getNextEvent(nextEventContext);
-        }
-
-        return currentEventContext;
-       }
-
-       public TmfExperimentContext seekEvent(long rank) {
-
-               TmfExperimentContext context;
-               int page = 0;           // The checkpoint page
-               int current = 0;        // The current event index (rank)
-               
-               // If there is no checkpoint created yet, start from the beginning
-               if (fCheckpoints.size() == 0) {
-                       context = seekLocation(null);
-               }
-               else {
-                       page = (int) rank / fIndexPageSize;
-                       if (page >= fCheckpoints.size()) {
-                               page = fCheckpoints.size() - 1;
-                       }
-                       context = seekLocation(fCheckpoints.elementAt(page).getLocation());
-                       current = page * fIndexPageSize;
-               }
-
-               // Position the traces at the requested index
-               while (current++ < rank) {
-                       getNextEvent(context);
-               }
-
-               return context;
-       }
-
-//     /**
-//      * Given an experiment event index, position the set of traces so a call
-//      * to getNextEvent() will retrieve the corresponding event.
-//      * 
-//      * @param index
-//      * @param context
-//      */
-//     private synchronized void positionTraces(long index, TmfExperimentContext context) {
-//
-//             // Extract the relevant information
-//             ITmfTrace[] traces = context.getTraces();
-//             TmfEvent[]  events = context.getEvents();
-//             TmfContext[] contexts = context.getContexts();
-//
-//             int page = 0;           // The checkpoint page
-//             int current = 0;        // The current event index (rank)
-//
-//             // If there is no checkpoint created yet, start from the beginning
-//             if (fCheckpoints.size() == 0) {
-//                     for (int i = 0; i < contexts.length; i++) {
-//                             contexts[i] = traces[i].seekLocation(null).clone();
-//                             events[i] = traces[i].parseEvent(contexts[i]);
-//                     }
-//             }
-//             else {
-//                     page = (int) index / fIndexPageSize;
-//                     if (page >= fCheckpoints.size()) {
-//                             page = fCheckpoints.size() - 1;
-//                     }
-//
-////                   TmfContext[] checkpoint = fCheckpoints.elementAt(page).getContexts();
-//                     for (int i = 0; i < contexts.length; i++) {
-//                             contexts[i] = checkpoint[i].clone();
-//                             events[i] = traces[i].parseEvent(contexts[i]);
-//                     }
-//                     current = page * fIndexPageSize;
-//             }
+            getNextEvent(context);
+            event = parseEvent(context);
+        }
+
+        if (event == null) {
+            context.setLocation(null);
+            context.setRank(ITmfContext.UNKNOWN_RANK);
+        }
+
+        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;
+    }
+
+    @Override
+    public TmfContext seekLocation(double ratio) {
+        TmfContext context = seekEvent((long) (ratio * getNbEvents()));
+        return context;
+    }
+
+    @Override
+    public double getLocationRatio(ITmfLocation<?> location) {
+        if (location instanceof TmfExperimentLocation) {
+            return (double) seekLocation(location).getRank() / getNbEvents();
+        }
+        return 0;
+    }
+
+    @Override
+    public ITmfLocation<?> getCurrentLocation() {
+        if (fExperimentContext != null) {
+            return fExperimentContext.getLocation();
+        }
+        return null;
+    }
+
+    /**
+     * Scan the next events from all traces and return the next one in chronological order.
+     * 
+     * @param context
+     * @return
+     */
+
+//     private void dumpContext(TmfExperimentContext context, boolean isBefore) {
+
+//             TmfContext context0 = context.getContexts()[0];
+//             TmfEvent   event0   = context.getEvents()[0];
+//             TmfExperimentLocation location0 = (TmfExperimentLocation) context.getLocation();
+//             long       rank0    = context.getRank();
+//             int        trace    = context.getLastTrace();
 //
-//             // Position the traces at the requested index
-//             while (current++ < index) {
-//                     getNextEvent(context);
-//             }
+//             StringBuffer result = new StringBuffer("Ctx: " + (isBefore ? "B " : "A "));
+//             
+//             result.append("[Ctx: fLoc= " + context0.getLocation().toString() + ", fRnk= " + context0.getRank() + "] ");
+//             result.append("[Evt: " + event0.getTimestamp().toString() + "] ");
+//             result.append("[Loc: fLoc= " + location0.getLocation()[0].toString() + ", fRnk= " + location0.getRanks()[0] + "] ");
+//             result.append("[Rnk: " + rank0 + "], [Trc: " + trace + "]");
+//             Tracer.trace(result.toString());
 //     }
 
-       /**
-        * Scan the next events from all traces and return the next one
-        * in chronological order.
-        * 
-        * @param context
-        * @return
-        */
-       public synchronized TmfEvent getNextEvent(TmfContext context) {
-               if (context instanceof TmfExperimentContext) {
-                       TmfExperimentContext expContext = (TmfExperimentContext) context;
-                       int trace = 0;
-                       TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
-                       if (expContext.getEvents()[trace] != null) {
-                               timestamp = expContext.getEvents()[trace].getTimestamp();
-                       }
-                       for (int i = 1; i < expContext.getTraces().length; i++) {
-                               if (expContext.getEvents()[i].getTimestamp() != null) {
-                                       TmfTimestamp otherTS = expContext.getEvents()[i].getTimestamp();
-                                       if (otherTS.compareTo(timestamp, true) < 0) {
-                                               trace = i;
-                                               timestamp = otherTS;
-                                       }
-                               }
-                       }
-                       TmfContext trcloc = expContext.getContexts()[trace];
-                       TmfEvent event = expContext.getTraces()[trace].parseEvent(trcloc);
-                       TmfExperimentLocation exploc = (TmfExperimentLocation) expContext.getLocation();
-                       exploc.getLocations()[trace] = trcloc.getLocation().clone();
-                       expContext.updateRank(1);
-                       expContext.getEvents()[trace] = expContext.getTraces()[trace].getNextEvent(trcloc);
-                       return event;
-               }
-       return null;
-       }
-
-       //      public TmfEvent getNextEvent(TmfExperimentContext context) {
-//             // TODO: Consider the time adjustment
-//             int trace = 0;
-//             TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
-//             if (context.getEvents()[trace] != null) {
-//                     timestamp = context.getEvents()[trace].getTimestamp();
-//             }
-//             for (int i = 1; i < context.getTraces().length; i++) {
-//                     if (context.getEvents()[i].getTimestamp() != null) {
-//                             TmfTimestamp otherTS = context.getEvents()[i].getTimestamp();
-//                             if (otherTS.compareTo(timestamp, true) < 0) {
-//                                     trace = i;
-//                                     timestamp = otherTS;
-//                             }
-//                     }
-//             }
-//             TmfEvent event = context.getTraces()[trace].getNextEvent(context.getContexts()[trace]);
-//             context.getEvents()[trace] = context.getTraces()[trace].parseEvent(context.getContexts()[trace]);
-//             return event;
-//     }
+    @Override
+    public synchronized TmfEvent getNextEvent(TmfContext context) {
 
-       public TmfEvent parseEvent(TmfContext context) {
-               // TODO Auto-generated method stub
-               return null;
-       }
-
-//     /**
-//      * Scan the next events from all traces and return the next one
-//      * in chronological order.
-//      * 
-//      * @param context
-//      * @return
-//      */
-//     private TmfTimestamp getNextEventTimestamp(TmfExperimentContext context) {
-//             // TODO: Consider the time adjustment
-//             int trace = 0;
-//             TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
-//             if (context.getEvents()[trace] != null) {
-//                     timestamp = context.getEvents()[trace].getTimestamp();
-//             }
-//             for (int i = 1; i < context.getTraces().length; i++) {
-//                     if (context.getEvents()[i].getTimestamp() != null) {
-//                             TmfTimestamp otherTS = context.getEvents()[i].getTimestamp();
-//                             if (otherTS.compareTo(timestamp, true) < 0) {
-//                                     trace = i;
-//                                     timestamp = otherTS;
-//                             }
-//                     }
+        // 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 timestamp;
-//     }
 
-       /* (non-Javadoc)
-        * @see java.lang.Object#toString()
-        */
-       @Override
-       public String toString() {
-               return "[TmfExperiment (" + fExperimentId + ")]";
-       }
+        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());
+            }
+        }
+    }
+
+    /*
+     * (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;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    @SuppressWarnings("nls")
+    public String toString() {
+        return "[TmfExperiment (" + getName() + ")]";
+    }
 
     // ------------------------------------------------------------------------
     // Indexing
     // ------------------------------------------------------------------------
 
-       /*
-        * The experiment holds the globally ordered events of its set of traces.
-        * It is expected to provide access to each individual event by index i.e.
-        * it must be possible to request the Nth event of the experiment.
-        * 
-        * The purpose of the index is to keep the information needed to rapidly
-        * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
-        * event).
-        */
-
-       // The index page size
-       private static final int DEFAULT_INDEX_PAGE_SIZE = 1000;
-       private final int fIndexPageSize;
-
-       // Indicates that an indexing job is already running
-       private Boolean fIndexing = false;
-       private Boolean fIndexed  = false;
-
-       // The indexing job
-       private IndexingJob job;
-
-       /**
-        * indexExperiment
-        * 
-        * Creates the experiment index.
-        */
-       public void indexExperiment(boolean waitForCompletion) {
-
-               synchronized(fIndexing) {
-                       if (fIndexed || fIndexing) {
-                               // An indexing job is already running but a new request came
-                               // in (probably due to a change in the trace set). The index
-                               // being currently built is therefore already invalid.
-                               // TODO: Cancel and restart the job
-                               // TODO: Add support for dynamically adding/removing traces
-                               return;
-                       }
-                       fIndexing = true;
-               }
-
-               job = new IndexingJob(fExperimentId);
-               job.schedule();
-
-       if (waitForCompletion) {
-               try {
-                       job.join();
-               } catch (InterruptedException e) {
-                       e.printStackTrace();
-               }
-       }
-       }
-
-       private class IndexingJob extends Job {
-
-               public IndexingJob(String name) {
-                       super(name);
-               }
-
-               /* (non-Javadoc)
-                * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
-                */
-               @Override
-               protected IStatus run(IProgressMonitor monitor) {
-
-                       // Minimal check
-                       if (fTraces.length == 0) {
-                   fIndexing = false;
-                               return Status.OK_STATUS;
-                       }
-
-                       monitor.beginTask("Indexing " + fExperimentId, IProgressMonitor.UNKNOWN);
-
-            int nbEvents = 0;
-            TmfTimestamp startTime = null;
-            TmfTimestamp lastTime  = null;
-
-            // Reset the index
-            fCheckpoints = new Vector<TmfCheckpoint>();
-            
-            try {
-               // Position the trace at the beginning
-               TmfExperimentContext context = seekLocation(null);
-               TmfExperimentLocation location = (TmfExperimentLocation) context.getLocation();
-
-                // Get the first event
-                       TmfEvent event = getNextEvent(context);
-                       if (event != null) {
-                    startTime = new TmfTimestamp(event.getTimestamp());
-                       }
-
-                       // Index the experiment
-                       while (event != null) {
-                       lastTime = event.getTimestamp();
-                               if ((nbEvents++ % fIndexPageSize) == 0) {
-                                       fCheckpoints.add(new TmfCheckpoint(lastTime, location.clone()));
-                               fNbEvents = nbEvents;
-                               fTimeRange = new TmfTimeRange(startTime, lastTime);
-                               notifyListeners(new TmfTimeRange(startTime, lastTime));
-
-                        monitor.worked(1);
-
-                        // Check monitor *after* fCheckpoints has been updated
-                        if (monitor.isCanceled()) {
-                            monitor.done();
-                               return Status.CANCEL_STATUS;
-                        }
+    /*
+     * The experiment holds the globally ordered events of its set of traces. It is expected to provide access to each
+     * individual event by index i.e. it must be possible to request the Nth event of the experiment.
+     * 
+     * The purpose of the index is to keep the information needed to rapidly restore the traces contexts at regular
+     * intervals (every INDEX_PAGE_SIZE event).
+     */
+
+    // The index page size
+    private static final int DEFAULT_INDEX_PAGE_SIZE = 5000;
+    protected int fIndexPageSize;
+    protected boolean fIndexing = false;
+    protected TmfTimeRange fIndexingPendingRange = TmfTimeRange.Null;
+
+//     private static BufferedWriter fEventLog = null;
+//     private static BufferedWriter openLogFile(String filename) {
+//             BufferedWriter outfile = null;
+//             try {
+//                     outfile = new BufferedWriter(new FileWriter(filename));
+//             } catch (IOException e) {
+//                     e.printStackTrace();
+//             }
+//             return outfile;
+//     }
+
+    protected boolean isIndexingBusy() {
+        synchronized (fCheckpoints) {
+            return fIndexing;
+        }
+    }
+
+    protected void indexExperiment(boolean waitForCompletion) {
+        indexExperiment(waitForCompletion, 0, TmfTimeRange.Eternity);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected void indexExperiment(boolean waitForCompletion, final int index, final TmfTimeRange timeRange) {
+
+        synchronized (fCheckpoints) {
+            if (fIndexing) {
+                return;
+            }
+            fIndexing = true;
+        }
+
+        final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
+            @Override
+            protected IStatus run(IProgressMonitor monitor) {
+                while (!monitor.isCanceled()) {
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException e) {
+                        return Status.OK_STATUS;
                     }
+                }
+                monitor.done();
+                return Status.OK_STATUS;
+            }
+        };
+        job.schedule();
 
-                    // We will need the contexts at the next iteration
-                    if ((nbEvents % fIndexPageSize) == 0) {
-                        location = (TmfExperimentLocation) context.getLocation();
-                               }
+//             fEventLog = openLogFile("TraceEvent.log");
+//        System.out.println(System.currentTimeMillis() + ": Experiment indexing started");
 
-                               event = getNextEvent(context);
+        ITmfEventRequest<TmfEvent> request = new TmfEventRequest<TmfEvent>(TmfEvent.class, timeRange, index, TmfDataRequest.ALL_DATA,
+                fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) { // PATA FOREGROUND
+
+//            long indexingStart = System.nanoTime();
+
+            TmfTimestamp startTime = (fTimeRange == TmfTimeRange.Null) ? null : fTimeRange.getStartTime();
+            TmfTimestamp lastTime = (fTimeRange == TmfTimeRange.Null) ? null : fTimeRange.getEndTime();
+            long initialNbEvents = fNbEvents;
+
+            @Override
+            public void handleStarted() {
+                super.handleStarted();
+            }
+
+            @Override
+            public void handleData(TmfEvent event) {
+                super.handleData(event);
+                if (event != null) {
+                    TmfTimestamp ts = event.getTimestamp();
+                    if (startTime == null)
+                        startTime = new TmfTimestamp(ts);
+                    lastTime = new TmfTimestamp(ts);
+                    if ((getNbRead() % fIndexPageSize) == 1 && getNbRead() != 1) {
+                        updateExperiment();
+                    }
                 }
+            }
+
+            @Override
+            public void handleSuccess() {
+//                long indexingEnd = System.nanoTime();
 
+                if (getRange() != TmfTimeRange.Eternity) {
+                    lastTime = getRange().getEndTime();
+                }
+                updateExperiment();
+//                System.out.println(System.currentTimeMillis() + ": Experiment indexing completed");
+
+//                long average = (indexingEnd - indexingStart) / fNbEvents;
+//                System.out.println(getName() + ": start=" + startTime + ", end=" + lastTime + ", elapsed="
+//                        + (indexingEnd * 1.0 - indexingStart) / 1000000000);
+//                System.out.println(getName() + ": nbEvents=" + fNbEvents + " (" + (average / 1000) + "."
+//                        + (average % 1000) + " us/evt)");
+                super.handleSuccess();
             }
-            finally {
-                synchronized(this) {
-                       fNbEvents = nbEvents;
-                       fTimeRange = new TmfTimeRange(startTime, lastTime);
-                       fIndexing = false;
-                       fIndexed = true;
+
+            @Override
+            public void handleCompleted() {
+                job.cancel();
+                super.handleCompleted();
+                synchronized (fCheckpoints) {
+                    fIndexing = false;
+                    if (fIndexingPendingRange != TmfTimeRange.Null) {
+                        indexExperiment(false, (int) fNbEvents, fIndexingPendingRange);
+                        fIndexingPendingRange = TmfTimeRange.Null;
+                    }
                 }
-                monitor.done();
             }
 
-//            dumpCheckpoints();
-
-            return Status.OK_STATUS;
-               }
-    }
-
-    protected void notifyListeners(TmfTimeRange range) {
-       broadcast(new TmfRangeSynchSignal(this, range, null));
-       }
-   
-       // ========================================================================
-       // Toubleshooting code
-       // ========================================================================
-
-//     private void dumpCheckpoints() {
-//             System.out.println("-----");
-//             System.out.println("Checkpoints of " + fExperimentId);
-//             for (int i = 0; i < fCheckpoints.size(); i++) {
-//             System.out.println("Entry:" + i);
-//             TmfCheckpoint checkpoint = fCheckpoints.get(i);
-//             long rank = 0; 
-//             for (int j = 0; j < fTraces.length; j++) {
-//                     ITmfTrace trace = fTraces[j];
-//             TmfExperimentContext context = seekLocation(checkpoint.getLocation());
-//             TmfContext[] traces = context.getContexts();
-//                     rank += context.getRank(); 
-//             TmfEvent event = fTraces[j].getNextEvent(new TmfContext(traces[j]));
-//             System.out.println("  ["  + trace.getName() + "] rank: " + context.getRank() + ", timestamp: " + event.getTimestamp());
-//             assert (checkpoint.getTimestamp().compareTo(event.getTimestamp(), false) == 0);
-//             }
-//             System.out.println("Sum of ranks: " + rank + " (expected: " + i * fIndexPageSize + ")");
-//        }
-//     }
+            private void updateExperiment() {
+                int nbRead = getNbRead();
+                if (startTime != null) {
+                    fTimeRange = new TmfTimeRange(startTime, new TmfTimestamp(lastTime));
+                }
+                if (nbRead != 0) {
+//                                     updateTimeRange();
+//                                     updateNbEvents();
+                    fNbEvents = initialNbEvents + nbRead;
+                    notifyListeners();
+                }
+            }
+        };
+
+        sendRequest((ITmfDataRequest<T>) request);
+        if (waitForCompletion)
+            try {
+                request.waitForCompletion();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+    }
+
+    protected void notifyListeners() {
+        broadcast(new TmfExperimentUpdatedSignal(this, this)); // , null));
+        broadcast(new TmfExperimentRangeUpdatedSignal(this, this, fTimeRange)); // , null));
+    }
 
     // ------------------------------------------------------------------------
     // Signal handlers
     // ------------------------------------------------------------------------
 
     @TmfSignalHandler
-    public void experimentSelected(TmfExperimentSelectedSignal signal) {
-               fCurrentExperiment = signal.getExperiment();
-//     if (signal.getExperiment() == this) {
-//             indexExperiment(true);
-//     }
+    public void experimentSelected(TmfExperimentSelectedSignal<T> signal) {
+        TmfExperiment<?> experiment = signal.getExperiment();
+        if (experiment == this) {
+            setCurrentExperiment(experiment);
+            indexExperiment(false);
+        }
     }
 
     @TmfSignalHandler
     public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
-//     indexExperiment(true);
     }
 
     @TmfSignalHandler
     public void traceUpdated(TmfTraceUpdatedSignal signal) {
-       // TODO: Incremental index update
-       synchronized(this) {
-               updateNbEvents();
-               updateTimeRange();
-       }
-               broadcast(new TmfExperimentUpdatedSignal(this, this, signal.getTrace()));
+        for (ITmfTrace<T> trace : fTraces) {
+            if (trace == signal.getTrace()) {
+                synchronized (fCheckpoints) {
+                    if (fIndexing) {
+                        if (fIndexingPendingRange == TmfTimeRange.Null) {
+                            fIndexingPendingRange = signal.getRange();
+                        } else {
+                            TmfTimestamp startTime = fIndexingPendingRange.getStartTime();
+                            TmfTimestamp endTime = fIndexingPendingRange.getEndTime();
+                            if (signal.getRange().getStartTime().compareTo(startTime) < 0) {
+                                startTime = signal.getRange().getStartTime();
+                            }
+                            if (signal.getRange().getEndTime().compareTo(endTime) > 0) {
+                                endTime = signal.getRange().getEndTime();
+                            }
+                            fIndexingPendingRange = new TmfTimeRange(startTime, endTime);
+                        }
+                        return;
+                    }
+                }
+                indexExperiment(false, (int) fNbEvents, signal.getRange());
+                return;
+            }
+        }
+    }
+
+    @Override
+    public String getPath() {
+        // TODO Auto-generated method stub
+        return null;
     }
 
 }
This page took 0.041679 seconds and 5 git commands to generate.