tmf: Offset traces ui
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTrace.java
index 5810801fe64ca18b45a4b2e9f4cd56a9e85d030e..167800c755d0aa66c145944cdfd56d101ce11a2d 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2013 Ericsson, École Polytechnique de Montréal
+ * Copyright (c) 2009, 2014 Ericsson, École Polytechnique de Montréal
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
 package org.eclipse.linuxtools.tmf.core.trace;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 
-import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.linuxtools.internal.tmf.core.Activator;
-import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
+import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule;
+import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper;
+import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager;
 import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider;
 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException;
 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
-import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
-import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
-import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
-import org.eclipse.linuxtools.tmf.core.statistics.TmfStateStatistics;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
 import org.eclipse.linuxtools.tmf.core.synchronization.ITmfTimestampTransform;
-import org.eclipse.linuxtools.tmf.core.synchronization.TmfTimestampTransform;
+import org.eclipse.linuxtools.tmf.core.synchronization.TimestampTransformFactory;
 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfTraceIndexer;
@@ -73,6 +69,10 @@ import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
  * accomplish this is by making the concrete class extend TmfTrace and
  * implement ITmfEventParser.
  * <p>
+ * When constructing an event, the concrete trace should use the trace's
+ * timestamp transform to create the timestamp, by either transforming the
+ * parsed time value directly or by using the method createTimestamp().
+ * <p>
  * The concrete class can either specify its own indexer or use the provided
  * TmfCheckpointIndexer (default). In this case, the trace cache size will be
  * used as checkpoint interval.
@@ -84,7 +84,7 @@ import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
  * @see ITmfTraceIndexer
  * @see ITmfEventParser
  */
-public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
+public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, ITmfTraceCompleteness {
 
     // ------------------------------------------------------------------------
     // Attributes
@@ -100,7 +100,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     private int fCacheSize = ITmfTrace.DEFAULT_TRACE_CACHE_SIZE;
 
     // The number of events collected (so far)
-    private long fNbEvents = 0;
+    private volatile long fNbEvents = 0;
 
     // The time span of the event stream
     private ITmfTimestamp fStartTime = TmfTimestamp.BIG_BANG;
@@ -115,22 +115,10 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     // The trace parser
     private ITmfEventParser fParser;
 
-    // The trace's statistics
-    private ITmfStatistics fStatistics;
-
-    /**
-     * The collection of state systems that are registered with this trace. Each
-     * sub-class can decide to add its (one or many) state system to this map
-     * during their {@link #buildStateSystem()}.
-     *
-     * @since 2.0
-     */
-    protected final Map<String, ITmfStateSystem> fStateSystems =
-            new LinkedHashMap<String, ITmfStateSystem>();
-
     private ITmfTimestampTransform fTsTransform;
 
-    private static final String SYNCHRONIZATION_FORMULA_FILE = "sync_formula"; //$NON-NLS-1$
+    private final Map<String, IAnalysisModule> fAnalysisModules =
+            Collections.synchronizedMap(new LinkedHashMap<String, IAnalysisModule>());
 
     // ------------------------------------------------------------------------
     // Construction
@@ -141,6 +129,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
      */
     public TmfTrace() {
         super();
+        fIndexer = createIndexer(DEFAULT_BLOCK_SIZE);
     }
 
     /**
@@ -158,9 +147,6 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
      * @param interval
      *            The trace streaming interval. You can use '0' for post-mortem
      *            traces.
-     * @param indexer
-     *            The trace indexer. You can pass 'null' to use a default
-     *            checkpoint indexer.
      * @param parser
      *            The trace event parser. Use 'null' if (and only if) the trace
      *            object itself is also the ITmfEventParser to be used.
@@ -172,13 +158,11 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
             final String path,
             final int cacheSize,
             final long interval,
-            final ITmfTraceIndexer indexer,
             final ITmfEventParser parser)
                     throws TmfTraceException {
         super();
         fCacheSize = (cacheSize > 0) ? cacheSize : ITmfTrace.DEFAULT_TRACE_CACHE_SIZE;
         fStreamingInterval = interval;
-        fIndexer = (indexer != null) ? indexer : new TmfCheckpointIndexer(this, fCacheSize);
         fParser = parser;
         initialize(resource, path, type);
     }
@@ -196,18 +180,35 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
         }
         fCacheSize = trace.getCacheSize();
         fStreamingInterval = trace.getStreamingInterval();
-        fIndexer = new TmfCheckpointIndexer(this);
         fParser = trace.fParser;
         initialize(trace.getResource(), trace.getPath(), trace.getEventType());
     }
 
+    /**
+     * Creates the indexer instance. Classes extending this class can override
+     * this to provide a different indexer implementation.
+     *
+     * @param interval the checkpoints interval
+     *
+     * @return the indexer
+     * @since 3.0
+     */
+    protected ITmfTraceIndexer createIndexer(int interval) {
+        return new TmfCheckpointIndexer(this, interval);
+    }
+
     // ------------------------------------------------------------------------
     // ITmfTrace - Initializers
     // ------------------------------------------------------------------------
 
+    @Override
+    public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> type, String name) throws TmfTraceException {
+        setName(name);
+        initTrace(resource, path, type);
+    }
+
     @Override
     public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> type) throws TmfTraceException {
-        fIndexer = new TmfCheckpointIndexer(this, fCacheSize);
         initialize(resource, path, type);
     }
 
@@ -229,11 +230,9 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
         }
         fPath = path;
         fResource = resource;
-        String traceName = (resource != null) ? resource.getName() : null;
-        // If no resource was provided, extract the display name the trace path
-        if (traceName == null) {
-            final int sep = path.lastIndexOf(IPath.SEPARATOR);
-            traceName = (sep >= 0) ? path.substring(sep + 1) : path;
+        String traceName = getName();
+        if (traceName == null || traceName.isEmpty()) {
+            traceName = (resource != null) ? resource.getName() : new Path(path).lastSegment();
         }
         if (fParser == null) {
             if (this instanceof ITmfEventParser) {
@@ -245,6 +244,10 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
         super.init(traceName, type);
         // register as VIP after super.init() because TmfComponent registers to signal manager there
         TmfSignalManager.registerVIP(this);
+        if (fIndexer != null) {
+            fIndexer.dispose();
+        }
+        fIndexer = createIndexer(fCacheSize);
     }
 
     /**
@@ -267,39 +270,78 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     }
 
     /**
-     * The default implementation of TmfTrace uses a TmfStatistics back-end.
-     * Override this if you want to specify another type (or none at all).
+     * Instantiate the applicable analysis modules and executes the analysis
+     * modules that are meant to be automatically executed
      *
-     * @return An IStatus indicating if the statistics could be built
-     *         successfully or not.
+     * @return An IStatus indicating whether the analysis could be run
+     *         successfully or not
      * @since 3.0
      */
-    protected IStatus buildStatistics() {
-        /*
-         * Initialize the statistics provider, but only if a Resource has been
-         * set (so we don't build it for experiments, for unit tests, etc.)
-         */
-        try {
-            fStatistics = (fResource == null ? null : new TmfStateStatistics(this) );
-        } catch (TmfTraceException e) {
-            return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
+    protected IStatus executeAnalysis() {
+        MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, null, null);
+        Map<String, IAnalysisModuleHelper> modules = TmfAnalysisManager.getAnalysisModules(this.getClass());
+        for (IAnalysisModuleHelper helper : modules.values()) {
+            try {
+                IAnalysisModule module = helper.newModule(this);
+                fAnalysisModules.put(module.getId(), module);
+                if (module.isAutomatic()) {
+                    status.add(module.schedule());
+                }
+            } catch (TmfAnalysisException e) {
+                status.add(new Status(IStatus.WARNING, Activator.PLUGIN_ID, e.getMessage()));
+            }
         }
-        return Status.OK_STATUS;
+        return status;
     }
 
     /**
-     * Build the state system(s) associated with this trace type.
-     *
-     * @return An IStatus indicating if the state system could be build
-     *         successfully or not.
      * @since 3.0
      */
-    protected IStatus buildStateSystem() {
-        /*
-         * Nothing is done in the base implementation, please specify
-         * how/if to register a new state system in derived classes.
-         */
-        return Status.OK_STATUS;
+    @Override
+    public IAnalysisModule getAnalysisModule(String analysisId) {
+        return fAnalysisModules.get(analysisId);
+    }
+
+
+    /**
+     * @since 3.0
+     */
+    @Override
+    public Iterable<IAnalysisModule> getAnalysisModules() {
+        synchronized (fAnalysisModules) {
+            Set<IAnalysisModule> modules = new HashSet<>(fAnalysisModules.values());
+            return modules;
+        }
+    }
+
+    /**
+     * @since 3.0
+     */
+    @Override
+    public <T extends IAnalysisModule> T getAnalysisModuleOfClass(Class<T> moduleClass, String id) {
+        Iterable<T> modules = getAnalysisModulesOfClass(moduleClass);
+        for (T module : modules) {
+            if (id.equals(module.getId())) {
+                return module;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @since 3.0
+     */
+    @Override
+    public <T> Iterable<T> getAnalysisModulesOfClass(Class<T> moduleClass) {
+        Set<T> modules = new HashSet<>();
+        synchronized (fAnalysisModules) {
+            for (Entry<String, IAnalysisModule> entry : fAnalysisModules.entrySet()) {
+                if (moduleClass.isAssignableFrom(entry.getValue().getClass())) {
+                    modules.add(moduleClass.cast(entry.getValue()));
+                }
+            }
+        }
+        return modules;
     }
 
     /**
@@ -312,14 +354,12 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
             getIndexer().dispose();
         }
 
-        /* Clean up the statistics */
-        if (fStatistics != null) {
-            fStatistics.dispose();
-        }
-
-        /* Clean up the state systems */
-        for (ITmfStateSystem ss : fStateSystems.values()) {
-            ss.dispose();
+        /* Clean up the analysis modules */
+        synchronized (fAnalysisModules) {
+            for (IAnalysisModule module : fAnalysisModules.values()) {
+                module.dispose();
+            }
+            fAnalysisModules.clear();
         }
 
         super.dispose();
@@ -330,8 +370,8 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     // ------------------------------------------------------------------------
 
     @Override
-    public Class<ITmfEvent> getEventType() {
-        return (Class<ITmfEvent>) super.getType();
+    public Class<? extends ITmfEvent> getEventType() {
+        return super.getType();
     }
 
     @Override
@@ -369,36 +409,12 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
         return fParser;
     }
 
-    /**
-     * @since 2.0
-     */
-    @Override
-    public ITmfStatistics getStatistics() {
-        return fStatistics;
-    }
-
-    /**
-     * @since 2.0
-     */
-    @Override
-    public final Map<String, ITmfStateSystem> getStateSystems() {
-        return Collections.unmodifiableMap(fStateSystems);
-    }
-
-    /**
-     * @since 2.0
-     */
-    @Override
-    public final void registerStateSystem(String id, ITmfStateSystem ss) {
-        fStateSystems.put(id, ss);
-    }
-
     // ------------------------------------------------------------------------
     // ITmfTrace - Trace characteristics getters
     // ------------------------------------------------------------------------
 
     @Override
-    public synchronized long getNbEvents() {
+    public long getNbEvents() {
         return fNbEvents;
     }
 
@@ -506,16 +522,6 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
         fStreamingInterval = (interval > 0) ? interval : 0;
     }
 
-    /**
-     * Set the trace indexer. Must be done at initialization time.
-     *
-     * @param indexer the trace indexer
-     * @since 3.0
-     */
-    protected void setIndexer(final ITmfTraceIndexer indexer) {
-        fIndexer = indexer;
-    }
-
     /**
      * Set the trace parser. Must be done at initialization time.
      *
@@ -649,16 +655,14 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
      * @since 2.0
      */
     @Override
-    public synchronized ITmfContext armRequest(final ITmfDataRequest request) {
+    public synchronized ITmfContext armRequest(final ITmfEventRequest request) {
         if (executorIsShutdown()) {
             return null;
         }
-        if ((request instanceof ITmfEventRequest)
-            && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest) request).getRange().getStartTime())
-            && (request.getIndex() == 0))
-        {
-            final ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime());
-            ((ITmfEventRequest) request).setStartIndex((int) context.getRank());
+        if (!TmfTimestamp.BIG_BANG.equals(request.getRange().getStartTime())
+                && (request.getIndex() == 0)) {
+            final ITmfContext context = seekEvent(request.getRange().getStartTime());
+            request.setStartIndex((int) context.getRank());
             return context;
 
         }
@@ -694,21 +698,12 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
          * The signal is either for this trace, or for an experiment containing
          * this trace.
          */
-        MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, null, null);
-        status.add(buildStatistics());
-        status.add(buildStateSystem());
+        IStatus status = executeAnalysis();
         if (!status.isOK()) {
             Activator.log(status);
         }
 
-        /* Refresh the project, so it can pick up new files that got created. */
-        try {
-            if (fResource != null) {
-                fResource.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
-            }
-        } catch (CoreException e) {
-            e.printStackTrace();
-        }
+        TmfTraceManager.refreshSupplementaryFiles(this);
 
         if (signal.getTrace() == this) {
             /* Additionally, the signal is directly for this trace. */
@@ -723,16 +718,13 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
                 return;
             }
 
-            final TmfTimeRange timeRange = new TmfTimeRange(getStartTime(), TmfTimestamp.BIG_CRUNCH);
-            final TmfTraceRangeUpdatedSignal rangeUpdatedsignal = new TmfTraceRangeUpdatedSignal(this, this, timeRange);
+            if (isComplete()) {
+                final TmfTimeRange timeRange = new TmfTimeRange(getStartTime(), TmfTimestamp.BIG_CRUNCH);
+                final TmfTraceRangeUpdatedSignal rangeUpdatedsignal = new TmfTraceRangeUpdatedSignal(this, this, timeRange);
 
-            // Broadcast in separate thread to prevent deadlock
-            new Thread() {
-                @Override
-                public void run() {
-                    broadcast(rangeUpdatedsignal);
-                }
-            }.start();
+                // Broadcast in separate thread to prevent deadlock
+                broadcastAsync(rangeUpdatedsignal);
+            }
             return;
         }
     }
@@ -751,26 +743,18 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     }
 
     /**
-     * Returns the file resource used to store synchronization formula. The file
-     * may not exist.
+     * Signal handler for the TmfTraceUpdatedSignal signal
      *
-     * @return the synchronization file
+     * @param signal The incoming signal
+     * @since 3.0
      */
-    private File getSyncFormulaFile() {
-        File file = null;
-        if (fResource instanceof IFolder) {
-            try {
-                String supplDirectory;
-
-                supplDirectory = fResource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
-
-                file = new File(supplDirectory + File.separator + SYNCHRONIZATION_FORMULA_FILE);
-
-            } catch (CoreException e) {
-
-            }
+    @TmfSignalHandler
+    public void traceUpdated(final TmfTraceUpdatedSignal signal) {
+        if (signal.getSource() == getIndexer()) {
+            fNbEvents = signal.getNbEvents();
+            fStartTime = signal.getRange().getStartTime();
+            fEndTime = signal.getRange().getEndTime();
         }
-        return file;
     }
 
     // ------------------------------------------------------------------------
@@ -783,27 +767,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     @Override
     public ITmfTimestampTransform getTimestampTransform() {
         if (fTsTransform == null) {
-            /* Check if a formula is stored somewhere in the resources */
-            File sync_file = getSyncFormulaFile();
-            if (sync_file != null && sync_file.exists()) {
-
-                try {
-                    FileInputStream fis = new FileInputStream(sync_file);
-                    ObjectInputStream ois = new ObjectInputStream(fis);
-                    fTsTransform = (ITmfTimestampTransform) ois.readObject();
-
-                    ois.close();
-                    fis.close();
-                } catch (ClassNotFoundException e1) {
-                    fTsTransform = TmfTimestampTransform.IDENTITY;
-                } catch (FileNotFoundException e1) {
-                    fTsTransform = TmfTimestampTransform.IDENTITY;
-                } catch (IOException e1) {
-                    fTsTransform = TmfTimestampTransform.IDENTITY;
-                }
-            } else {
-                fTsTransform = TmfTimestampTransform.IDENTITY;
-            }
+            fTsTransform = TimestampTransformFactory.getTimestampTransform(getResource());
         }
         return fTsTransform;
     }
@@ -814,28 +778,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
     @Override
     public void setTimestampTransform(final ITmfTimestampTransform tt) {
         fTsTransform = tt;
-
-        /* Save the timestamp transform to a file */
-        File sync_file = getSyncFormulaFile();
-        if (sync_file != null) {
-            if (sync_file.exists()) {
-                sync_file.delete();
-            }
-            FileOutputStream fos;
-            ObjectOutputStream oos;
-
-            /* Save the header of the file */
-            try {
-                fos = new FileOutputStream(sync_file, false);
-                oos = new ObjectOutputStream(fos);
-
-                oos.writeObject(fTsTransform);
-                oos.close();
-                fos.close();
-            } catch (IOException e1) {
-                Activator.logError("Error writing timestamp transform for trace", e1); //$NON-NLS-1$
-            }
-        }
+        TimestampTransformFactory.setTimestampTransform(getResource(), tt);
     }
 
     /**
@@ -843,7 +786,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
      */
     @Override
     public ITmfTimestamp createTimestamp(long ts) {
-        return new TmfTimestamp(getTimestampTransform().transform(ts));
+        return new TmfNanoTimestamp(getTimestampTransform().transform(ts));
     }
 
     // ------------------------------------------------------------------------
@@ -858,4 +801,26 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace {
                 + ", fEndTime=" + fEndTime + ", fStreamingInterval=" + fStreamingInterval + "]";
     }
 
+    /**
+     * @since 3.1
+     */
+    @Override
+    public boolean isComplete() {
+        /*
+         * Be default, all traces are "complete" which means no more data will
+         * be added later
+         */
+        return true;
+    }
+
+    /**
+     * @since 3.1
+     */
+    @Override
+    public void setComplete(boolean isComplete) {
+        /*
+         * This should be overridden by trace classes that can support live
+         * reading (traces in an incomplete state)
+         */
+    }
 }
This page took 0.031743 seconds and 5 git commands to generate.