From 8c8bf09fe0f30119bc8da63ebf93724ad5f5c6b3 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Mon, 31 May 2010 19:24:53 +0000 Subject: [PATCH] --- org.eclipse.linuxtools.tmf/.classpath | 7 + org.eclipse.linuxtools.tmf/.options | 2 + org.eclipse.linuxtools.tmf/.project | 28 + org.eclipse.linuxtools.tmf/ChangeLog | 3 + .../META-INF/MANIFEST.MF | 19 + org.eclipse.linuxtools.tmf/build.properties | 5 + org.eclipse.linuxtools.tmf/plugin.properties | 3 + .../eclipse/linuxtools/tmf/TmfCorePlugin.java | 82 +++ .../org/eclipse/linuxtools/tmf/Tracer.java | 24 + .../tmf/component/ITmfComponent.java | 43 ++ .../tmf/component/ITmfDataProvider.java | 17 + .../tmf/component/TmfComponent.java | 77 ++ .../tmf/component/TmfDataProvider.java | 301 ++++++++ .../tmf/component/TmfEventProvider.java | 64 ++ .../tmf/component/TmfProviderManager.java | 109 +++ .../eclipse/linuxtools/tmf/event/TmfData.java | 25 + .../linuxtools/tmf/event/TmfEvent.java | 193 +++++ .../linuxtools/tmf/event/TmfEventContent.java | 169 +++++ .../linuxtools/tmf/event/TmfEventField.java | 123 ++++ .../tmf/event/TmfEventReference.java | 90 +++ .../linuxtools/tmf/event/TmfEventSource.java | 90 +++ .../linuxtools/tmf/event/TmfEventType.java | 147 ++++ .../tmf/event/TmfNoSuchFieldException.java | 30 + .../linuxtools/tmf/event/TmfTimeRange.java | 125 ++++ .../linuxtools/tmf/event/TmfTimestamp.java | 306 ++++++++ .../linuxtools/tmf/event/TmfTraceEvent.java | 147 ++++ .../tmf/experiment/TmfExperiment.java | 682 ++++++++++++++++++ .../experiment/TmfExperimentCheckpoint.java | 91 +++ .../tmf/experiment/TmfExperimentContext.java | 120 +++ .../tmf/experiment/TmfExperimentLocation.java | 46 ++ .../tmf/parser/ITmfEventParser.java | 33 + .../tmf/request/ITmfDataRequest.java | 96 +++ .../tmf/request/ITmfEventRequest.java | 30 + .../tmf/request/TmfCoalescedDataRequest.java | 147 ++++ .../tmf/request/TmfCoalescedEventRequest.java | 121 ++++ .../tmf/request/TmfDataRequest.java | 381 ++++++++++ .../tmf/request/TmfEventRequest.java | 103 +++ .../tmf/request/TmfRequestExecutor.java | 122 ++++ .../tmf/signal/TmfEndSynchSignal.java | 26 + .../signal/TmfExperimentSelectedSignal.java | 40 + .../signal/TmfExperimentUpdatedSignal.java | 51 ++ .../tmf/signal/TmfRangeSynchSignal.java | 42 ++ .../linuxtools/tmf/signal/TmfSignal.java | 48 ++ .../tmf/signal/TmfSignalHandler.java | 29 + .../tmf/signal/TmfSignalManager.java | 132 ++++ .../tmf/signal/TmfSignalTracer.java | 38 + .../tmf/signal/TmfStartSynchSignal.java | 27 + .../tmf/signal/TmfTimeSynchSignal.java | 43 ++ .../tmf/signal/TmfTraceUpdatedSignal.java | 50 ++ .../linuxtools/tmf/trace/ITmfContext.java | 31 + .../linuxtools/tmf/trace/ITmfLocation.java | 28 + .../linuxtools/tmf/trace/ITmfTrace.java | 81 +++ .../linuxtools/tmf/trace/TmfCheckpoint.java | 110 +++ .../linuxtools/tmf/trace/TmfContext.java | 112 +++ .../linuxtools/tmf/trace/TmfLocation.java | 88 +++ .../linuxtools/tmf/trace/TmfTrace.java | 467 ++++++++++++ 56 files changed, 5644 insertions(+) create mode 100644 org.eclipse.linuxtools.tmf/.classpath create mode 100644 org.eclipse.linuxtools.tmf/.options create mode 100644 org.eclipse.linuxtools.tmf/.project create mode 100644 org.eclipse.linuxtools.tmf/ChangeLog create mode 100644 org.eclipse.linuxtools.tmf/META-INF/MANIFEST.MF create mode 100644 org.eclipse.linuxtools.tmf/build.properties create mode 100644 org.eclipse.linuxtools.tmf/plugin.properties create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/TmfCorePlugin.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/Tracer.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfComponent.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfDataProvider.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfComponent.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfDataProvider.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfEventProvider.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfProviderManager.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfData.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEvent.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventContent.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventField.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventReference.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventSource.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventType.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfNoSuchFieldException.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimeRange.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimestamp.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTraceEvent.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperiment.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentCheckpoint.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentContext.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentLocation.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/parser/ITmfEventParser.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfDataRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfEventRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedDataRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedEventRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfDataRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfEventRequest.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfRequestExecutor.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfEndSynchSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentSelectedSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentUpdatedSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfRangeSynchSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalHandler.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalManager.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalTracer.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfStartSynchSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTimeSynchSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTraceUpdatedSignal.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfContext.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfLocation.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfTrace.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfCheckpoint.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfContext.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfLocation.java create mode 100644 org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfTrace.java diff --git a/org.eclipse.linuxtools.tmf/.classpath b/org.eclipse.linuxtools.tmf/.classpath new file mode 100644 index 0000000000..64c5e31b7a --- /dev/null +++ b/org.eclipse.linuxtools.tmf/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.eclipse.linuxtools.tmf/.options b/org.eclipse.linuxtools.tmf/.options new file mode 100644 index 0000000000..8b5ba37472 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/.options @@ -0,0 +1,2 @@ +org.eclipse.linuxtools.tmf/trace=false + diff --git a/org.eclipse.linuxtools.tmf/.project b/org.eclipse.linuxtools.tmf/.project new file mode 100644 index 0000000000..93ef70665d --- /dev/null +++ b/org.eclipse.linuxtools.tmf/.project @@ -0,0 +1,28 @@ + + + org.eclipse.linuxtools.tmf + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.eclipse.linuxtools.tmf/ChangeLog b/org.eclipse.linuxtools.tmf/ChangeLog new file mode 100644 index 0000000000..9df424b2d5 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/ChangeLog @@ -0,0 +1,3 @@ +2009-06-16 Andrew Overholt + + * META-INF/MANIFEST.MF: Change provider from Ericsson to Eclipse. \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..2ea69c6057 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.linuxtools.tmf +Bundle-Version: 0.2.0.qualifier +Bundle-Activator: org.eclipse.linuxtools.tmf.TmfCorePlugin +Bundle-Vendor: %Bundle-Vendor +Require-Bundle: org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Export-Package: org.eclipse.linuxtools.tmf, + org.eclipse.linuxtools.tmf.component, + org.eclipse.linuxtools.tmf.event, + org.eclipse.linuxtools.tmf.experiment, + org.eclipse.linuxtools.tmf.parser, + org.eclipse.linuxtools.tmf.request, + org.eclipse.linuxtools.tmf.signal, + org.eclipse.linuxtools.tmf.trace +Bundle-Localization: plugin diff --git a/org.eclipse.linuxtools.tmf/build.properties b/org.eclipse.linuxtools.tmf/build.properties new file mode 100644 index 0000000000..4d2c73481e --- /dev/null +++ b/org.eclipse.linuxtools.tmf/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + plugin.properties,\ + . diff --git a/org.eclipse.linuxtools.tmf/plugin.properties b/org.eclipse.linuxtools.tmf/plugin.properties new file mode 100644 index 0000000000..c871b62008 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/plugin.properties @@ -0,0 +1,3 @@ +#Properties file for org.eclipse.linuxtools.tmf +Bundle-Vendor = Eclipse Linux Tools +Bundle-Name = TMF - Tracing and Monitoring Framework (Incubation) \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/TmfCorePlugin.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/TmfCorePlugin.java new file mode 100644 index 0000000000..16378a895b --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/TmfCorePlugin.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf; + +import org.eclipse.core.runtime.Plugin; +import org.osgi.framework.BundleContext; + +/** + * TmfCorePlugin + *

+ * The activator class controls the plug-in life cycle. No more than one such + * plug-in can exist at any time. + */ +public class TmfCorePlugin extends Plugin { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.linuxtools.tmf"; + + // The shared instance + private static TmfCorePlugin fPlugin; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * The constructor + */ + public TmfCorePlugin() { + setDefault(this); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the shared instance + */ + public static TmfCorePlugin getDefault() { + return fPlugin; + } + + /** + * @param plugin the shared instance + */ + private static void setDefault(TmfCorePlugin plugin) { + fPlugin = plugin; + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + setDefault(this); + Tracer.init(); + } + + @Override + public void stop(BundleContext context) throws Exception { + setDefault(null); + super.stop(context); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/Tracer.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/Tracer.java new file mode 100644 index 0000000000..089e8801b7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/Tracer.java @@ -0,0 +1,24 @@ +package org.eclipse.linuxtools.tmf; + +import org.eclipse.core.runtime.Platform; + +public class Tracer { + + static Boolean TRACE = Boolean.FALSE; + + private static String pluginID = TmfCorePlugin.PLUGIN_ID; + + public static void init() { + String traceKey = Platform.getDebugOption(pluginID + "/trace"); + + if (traceKey != null) { + TRACE = (new Boolean(traceKey)).booleanValue(); + } + } + + public static void trace(String message) { + if (TRACE) { + System.out.println(Thread.currentThread() + ": " + message); + } + } +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfComponent.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfComponent.java new file mode 100644 index 0000000000..b82ad6d7a8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfComponent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.component; + +import org.eclipse.linuxtools.tmf.signal.TmfSignal; + +/** + * ITmfComponent + *

+ * This is the basic interface of all the TMF components. + *

+ * Currently, it only addresses the inter-component signaling. + */ +public interface ITmfComponent { + + /** + * Get the component ID + */ + public String getName(); + + /** + * Dispose of the component + */ + public void dispose(); + + /** + * Broadcast a signal to all the interested listeners. + * + * @param signal + */ + public void broadcast(TmfSignal signal); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfDataProvider.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfDataProvider.java new file mode 100644 index 0000000000..8d50d905f4 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/ITmfDataProvider.java @@ -0,0 +1,17 @@ +package org.eclipse.linuxtools.tmf.component; + +import org.eclipse.linuxtools.tmf.event.TmfData; +import org.eclipse.linuxtools.tmf.request.ITmfDataRequest; + +public interface ITmfDataProvider { + + /** + * Queues the request for processing. + * + * If the request can't be serviced, it will fail (i.e. isFailed() will be set). + * + * @param request The request to process + */ + public void sendRequest(ITmfDataRequest request); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfComponent.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfComponent.java new file mode 100644 index 0000000000..276045842d --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfComponent.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.component; + +import org.eclipse.linuxtools.tmf.signal.TmfSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; + +/** + * TmfComponent + *

+ * This is the base class of the TMF components. + *

+ * Currently, it only addresses the inter-component signaling. + */ +public abstract class TmfComponent implements ITmfComponent { + + private String fName; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public TmfComponent(String name) { + fName = name; + TmfSignalManager.register(this); + } + + public TmfComponent(TmfComponent oldComponent) { + this.fName = oldComponent.fName; + + // Should we register? Probably not but I'm not quite sure what this does + //register(); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.component.ITmfComponent#getName() + */ + protected void setName(String name) { + fName = name; + } + + // ------------------------------------------------------------------------ + // ITmfComponent + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.component.ITmfComponent#getName() + */ + public String getName() { + return fName; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.component.ITmfComponent#dispose() + */ + public void dispose() { + TmfSignalManager.deregister(this); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.component.ITmfComponent#broadcast(org.eclipse.linuxtools.tmf.signal.TmfSignal) + */ + public void broadcast(TmfSignal signal) { + TmfSignalManager.dispatchSignal(signal); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfDataProvider.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfDataProvider.java new file mode 100644 index 0000000000..d93a6b6f74 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfDataProvider.java @@ -0,0 +1,301 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.component; + +import java.lang.reflect.Array; +import java.util.Vector; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; + +import org.eclipse.linuxtools.tmf.Tracer; +import org.eclipse.linuxtools.tmf.event.TmfData; +import org.eclipse.linuxtools.tmf.request.ITmfDataRequest; +import org.eclipse.linuxtools.tmf.request.TmfCoalescedDataRequest; +import org.eclipse.linuxtools.tmf.request.TmfDataRequest; +import org.eclipse.linuxtools.tmf.request.TmfRequestExecutor; +import org.eclipse.linuxtools.tmf.signal.TmfEndSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfStartSynchSignal; +import org.eclipse.linuxtools.tmf.trace.ITmfContext; + +/** + * TmfProvider + *

+ * The TmfProvider is a provider for a data of type . + *

+ * This abstract class implements the housekeeking methods to register/ + * deregister the event provider and to handle generically the event requests. + *

+ * The concrete class can either re-implement processRequest() entirely or + * just implement the hooks (initializeContext() and getNext()). + *

+ * TODO: Add support for providing multiple data types. + */ +public abstract class TmfDataProvider extends TmfComponent implements ITmfDataProvider { + + final protected Class fType; + + public static final int DEFAULT_QUEUE_SIZE = 1000; + protected final int fQueueSize; + protected final BlockingQueue fDataQueue; + protected final TmfRequestExecutor fExecutor; + + private int fCoalescingLevel = 0; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public TmfDataProvider(String name, Class type) { + this(name, type, DEFAULT_QUEUE_SIZE); + } + + protected TmfDataProvider(String name, Class type, int queueSize) { + super(name); + fType = type; + fQueueSize = queueSize; + fDataQueue = (queueSize > 1) ? new LinkedBlockingQueue(fQueueSize) : new SynchronousQueue(); + + Tracer.trace(getName() + " created"); + + fExecutor = new TmfRequestExecutor(); + fCoalescingLevel = 0; + + TmfProviderManager.register(fType, this); + Tracer.trace(getName() + " started"); +} + + public TmfDataProvider(TmfDataProvider other) { + super(other); + fType = other.fType; + fQueueSize = other.fQueueSize; + fDataQueue = (fQueueSize > 1) ? new LinkedBlockingQueue(fQueueSize) : new SynchronousQueue(); + + fExecutor = new TmfRequestExecutor(); + fCoalescingLevel = 0; + } + + @Override + public void dispose() { + TmfProviderManager.deregister(fType, this); + fExecutor.stop(); + Tracer.trace(getName() + " stopped"); + super.dispose(); + } + + public int getQueueSize() { + return fQueueSize; + } + + public Class getType() { + return fType; + } + + // ------------------------------------------------------------------------ + // ITmfRequestHandler + // ------------------------------------------------------------------------ + + public synchronized void sendRequest(final ITmfDataRequest request) { + + if (fCoalescingLevel > 0) { + // We are in coalescing mode: client should NEVER wait + // (otherwise we will have deadlock...) + coalesceDataRequest(request); + } else { + // Process the request immediately + queueRequest(request); + } + } + + /** + * This method queues the coalesced requests. + * + * @param thread + */ + private synchronized void fireRequests() { + for (TmfDataRequest request : fPendingCoalescedRequests) { + queueRequest(request); + } + fPendingCoalescedRequests.clear(); + } + + // ------------------------------------------------------------------------ + // Coalescing (primitive test...) + // ------------------------------------------------------------------------ + + protected Vector> fPendingCoalescedRequests = new Vector>(); + + protected synchronized void newCoalescedDataRequest(ITmfDataRequest request) { + TmfCoalescedDataRequest coalescedRequest = + new TmfCoalescedDataRequest(fType, request.getIndex(), request.getNbRequested(), request.getBlockize()); + coalescedRequest.addRequest(request); + fPendingCoalescedRequests.add(coalescedRequest); + } + + protected synchronized void coalesceDataRequest(ITmfDataRequest request) { + for (TmfCoalescedDataRequest req : fPendingCoalescedRequests) { + if (req.isCompatible(request)) { + req.addRequest(request); + return; + } + } + newCoalescedDataRequest(request); + } + + // ------------------------------------------------------------------------ + // Request processing + // ------------------------------------------------------------------------ + + protected void queueRequest(final ITmfDataRequest request) { + + final String provider = getName(); + + // Process the request + Thread thread = new Thread() { + + @Override + public void run() { + + // Extract the generic information + int blockSize = request.getBlockize(); + int nbRequested = request.getNbRequested(); + + // Create the result buffer + Vector result = new Vector(); + int nbRead = 0; + + // Initialize the execution + ITmfContext context = armRequest(request); + if (context == null) { + request.fail(); + return; + } + + // Get the ordered events + Tracer.trace("Request #" + request.getRequestId() + " is serviced by " + provider); + T data = getNext(context); + Tracer.trace("Request #" + request.getRequestId() + " read first event"); + while (data != null && !isCompleted(request, data, nbRead)) + { + result.add(data); + if (++nbRead % blockSize == 0) { + pushData(request, result); + } + // To avoid an unnecessary read passed the last data requested + if (nbRead < nbRequested) { + data = getNext(context); + if (data == null || data.isNullRef()) { + Tracer.trace("Request #" + request.getRequestId() + " end of data"); + } + } + } + pushData(request, result); + request.done(); + } + }; + fExecutor.execute(thread); + } + + /** + * Format the result data and forwards it to the requester. + * Note: after handling, the data is *removed*. + * + * @param request + * @param data + */ + @SuppressWarnings("unchecked") + protected void pushData(ITmfDataRequest request, Vector data) { + synchronized(request) { + if (!request.isCompleted()) { + T[] result = (T[]) Array.newInstance(fType, data.size()); + data.toArray(result); + request.setData(result); + request.handleData(); + data.removeAllElements(); + } + } + } + + /** + * Initialize the provider based on the request. The context is + * provider specific and will be updated by getNext(). + * + * @param request + * @return an application specific context; null if request can't be serviced + */ + public abstract ITmfContext armRequest(ITmfDataRequest request); + + /** + * Return the next piece of data based on the context supplied. The context + * would typically be updated for the subsequent read. + * + * @param context + * @return + */ + public T getNext(ITmfContext context) { + try { + T event = fDataQueue.take(); + return event; + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Makes the generated result data available for getNext() + * + * @param data + */ + public void queueResult(T data) { + try { + fDataQueue.put(data); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + /** + * Checks if the data meets the request completion criteria. + * + * @param request + * @param data + * @return + */ + public boolean isCompleted(ITmfDataRequest request, T data, int nbRead) { + return request.isCompleted() || nbRead >= request.getNbRequested() || data.isNullRef(); + } + + // ------------------------------------------------------------------------ + // Signal handlers + // ------------------------------------------------------------------------ + + @TmfSignalHandler + public void startSynch(TmfStartSynchSignal signal) { + synchronized(this) { + fCoalescingLevel++; + } + } + + @TmfSignalHandler + public void endSynch(TmfEndSynchSignal signal) { + synchronized(this) { + fCoalescingLevel--; + if (fCoalescingLevel == 0) { + fireRequests(); + } + } + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfEventProvider.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfEventProvider.java new file mode 100644 index 0000000000..a6d1c35d51 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfEventProvider.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.component; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +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.TmfCoalescedEventRequest; + +/** + * TmfEventProvider + *

+ * Implement me. Please. + */ +public abstract class TmfEventProvider extends TmfDataProvider { + + public TmfEventProvider(String name, Class type) { + super(name, type); + } + + public TmfEventProvider(String name, Class type, int queueSize) { + super(name, type, queueSize); + } + + public TmfEventProvider(TmfEventProvider oldProvider) { + super(oldProvider); + } + + @Override + public boolean isCompleted(ITmfDataRequest request, T data, int nbRead) { + boolean dataRequestCompleted = super.isCompleted(request, data, nbRead); + if (!dataRequestCompleted && request instanceof ITmfEventRequest && !data.isNullRef()) { + TmfTimestamp endTime = ((ITmfEventRequest) request).getRange().getEndTime(); + return data.getTimestamp().compareTo(endTime, false) > 0; + } + return dataRequestCompleted; + } + + @Override + protected synchronized void newCoalescedDataRequest(ITmfDataRequest request) { + if (request instanceof ITmfEventRequest) { + ITmfEventRequest eventRequest = (ITmfEventRequest) request; + TmfCoalescedEventRequest coalescedRequest = + new TmfCoalescedEventRequest(fType, eventRequest.getRange(), eventRequest.getNbRequested(), eventRequest.getBlockize()); + coalescedRequest.addRequest(eventRequest); + fPendingCoalescedRequests.add(coalescedRequest); + } + else { + super.newCoalescedDataRequest(request); + } + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfProviderManager.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfProviderManager.java new file mode 100644 index 0000000000..0b71a53a36 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/component/TmfProviderManager.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.linuxtools.tmf.event.TmfData; + +/** + * TmfProviderManager.java + *

+ * Singleton that keeps track of the event providers. + */ +public class TmfProviderManager { + + // ------------------------------------------------------------------------ + // No constructor + // ------------------------------------------------------------------------ + + private TmfProviderManager() {} + + // ------------------------------------------------------------------------ + // Keeps track of the providers for each event type + // ------------------------------------------------------------------------ + + private static Map, List>> fProviders = + new HashMap, List>>(); + + /** + * Registers [provider] as a provider of [eventType] + * + * @param eventType + * @param provider + */ + public static void register(Class eventType, TmfDataProvider provider) { + if (fProviders.get(eventType) == null) + fProviders.put(eventType, new ArrayList>()); + fProviders.get(eventType).add(provider); + } + + /** + * Re-registers [provider] as a provider of [eventType] + * + * @param dataClass + * @param provider + */ + public static void deregister(Class dataClass, TmfDataProvider provider) { + List> list = fProviders.get(dataClass); + if (list != null) { + list.remove(provider); + if (list.size() == 0) + fProviders.remove(dataClass); + } + } + + /** + * Returns the list of components that provide [eventType] + * + * @param dataClass + * @return + */ + @SuppressWarnings("unchecked") + public static TmfDataProvider[] getProviders(Class dataClass) { + List> list = fProviders.get(dataClass); + if (list == null) + list = new ArrayList>(); + TmfDataProvider[] result = new TmfDataProvider[list.size()]; + return list.toArray(result); + } + + /** + * Returns the list of components of type [providerType] that provide [eventType] + * + * @param type + * @param clazz + * @return + */ + @SuppressWarnings("unchecked") + public static TmfDataProvider[] getProviders(Class dataClass, Class> providerClass) { + if (providerClass == null) { + return getProviders(dataClass); + } + TmfDataProvider[] list = getProviders(dataClass); + List> result = new ArrayList>(); + if (list != null) { + for (TmfDataProvider provider : list) { + if (provider.getClass() == providerClass) { + result.add(provider); + } + } + } + TmfDataProvider[] array = new TmfDataProvider[result.size()]; + return result.toArray(array); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfData.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfData.java new file mode 100644 index 0000000000..1576c01170 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfData.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfData + *

+ * This is just an empty base class for the data meant to navigate in the + * framework. + */ +public abstract class TmfData { + + public abstract boolean isNullRef(); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEvent.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEvent.java new file mode 100644 index 0000000000..ac2fafa548 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEvent.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfEvent + *

+ * The basic event structure in the TMF. In its canonical form, an event has: + *

+ * For convenience, a free-form reference field is also provided. It could be + * used as e.g. a location marker in the event stream to distinguish between + * otherwise identical events. + * + * Notice that for performance reasons TmfEvent is NOT immutable. If a copy + * of the event is needed, use the copy constructor. + */ +public class TmfEvent extends TmfData { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + public static final TmfEvent NullEvent = new TmfEvent(); + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected TmfTimestamp fEffectiveTimestamp; + protected TmfTimestamp fOriginalTimestamp; + protected TmfEventSource fSource; + protected TmfEventType fType; + protected TmfEventReference fReference; + + // Content requires a reference to the parent event so it is initialized + // using setContent() + protected TmfEventContent fContent; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param originalTS the original timestamp + * @param effectiveTS the effective timestamp + * @param source the event source (generator) + * @param type the event type + * @param reference a free-form reference field + */ + public TmfEvent(TmfTimestamp originalTS, TmfTimestamp effectiveTS, + TmfEventSource source, TmfEventType type, TmfEventReference reference) + { + fOriginalTimestamp = originalTS; + fEffectiveTimestamp = effectiveTS; + fSource = source; + fType = type; + fReference = reference; + } + + /** + * @param timestamp the effective timestamp + * @param source the event source (generator) + * @param type the event type + * @param reference a free-form reference field + */ + public TmfEvent(TmfTimestamp timestamp, TmfEventSource source, + TmfEventType type, TmfEventReference reference) + { + this(timestamp, timestamp, source, type, reference); + } + + /** + * Copy constructor + * + * @param other the original event + */ + public TmfEvent(TmfEvent other) { + if (other == null) + throw new IllegalArgumentException(); + fOriginalTimestamp = new TmfTimestamp(other.fOriginalTimestamp); + fEffectiveTimestamp = new TmfTimestamp(other.fEffectiveTimestamp); + fSource = new TmfEventSource(other.fSource); + fType = new TmfEventType(other.fType); + fContent = new TmfEventContent(other.fContent); + fReference = new TmfEventReference(other.fReference); + } + + private TmfEvent() { + } + + @Override + public boolean isNullRef() { + return this == NullEvent; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the effective event timestamp + */ + public TmfTimestamp getTimestamp() { + return fEffectiveTimestamp; + } + + /** + * @return the original event timestamp + */ + public TmfTimestamp getOriginalTimestamp() { + return fOriginalTimestamp; + } + + /** + * @return the event source + */ + public TmfEventSource getSource() { + return fSource; + } + + /** + * @return the event type + */ + public TmfEventType getType() { + return fType; + } + + /** + * @return the event content + */ + public TmfEventContent getContent() { + return fContent; + } + + /** + * @return the event reference + */ + public TmfEventReference getReference() { + return fReference; + } + + /** + * @param content the new event content + */ + public void setContent(TmfEventContent content) { + fContent = content; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + fSource.hashCode(); + result = 37 * result + fType.hashCode(); + result = 37 * result + fEffectiveTimestamp.hashCode(); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEvent)) + return false; + TmfEvent o = (TmfEvent) other; + return fEffectiveTimestamp.equals(o.fEffectiveTimestamp) && + fSource.equals(o.fSource) && + fType.equals(o.fType) && + fContent.equals(o.fContent); + } + + @Override + public String toString() { + return "[TmfEvent(" + fEffectiveTimestamp + "," + fSource + "," + fType + "," + fContent + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventContent.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventContent.java new file mode 100644 index 0000000000..662ad85fb8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventContent.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + + +/** + * TmfEventContent + *

+ * The event content. + */ +public class TmfEventContent { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected TmfEvent fParentEvent; + protected Object fRawContent; + protected Object[] fFields; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param parent the parent event (owner) + * @param content the raw content + */ + public TmfEventContent(TmfEvent parent, Object content) { + fParentEvent = parent; + fRawContent = content; + } + + /** + * @param other the original event content + */ + public TmfEventContent(TmfEventContent other) { + if (other == null) + throw new IllegalArgumentException(); + fParentEvent = other.fParentEvent; + fRawContent = other.fRawContent; + fFields = other.fFields; + } + + @SuppressWarnings("unused") + private TmfEventContent() { + throw new AssertionError(); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the parent (containing) event + */ + public TmfEvent getEvent() { + return fParentEvent; + } + + /** + * @return the event type + */ + public TmfEventType getType() { + return fParentEvent.getType(); + } + + /** + * @return the raw content + */ + public Object getContent() { + return fRawContent; + } + + /** + * Returns the list of fields in the same order as TmfEventType.getLabels() + * + * @return the ordered set of fields (optional fields might be null) + */ + public Object[] getFields() { + if (fFields == null) { + parseContent(); + } + return fFields; + } + + /** + * @param id the field id + * @return the corresponding field + * @throws TmfNoSuchFieldException + */ + public Object getField(String id) throws TmfNoSuchFieldException { + if (fFields == null) { + parseContent(); + } + return fFields[getType().getFieldIndex(id)]; + } + + /** + * @param n the field index as per TmfEventType.getLabels() + * @return the corresponding field (null if non-existing) + */ + public Object getField(int n) { + if (fFields == null) { + parseContent(); + } + if (n >= 0 && n < fFields.length) + return fFields[n]; + + return null; + } + + // ------------------------------------------------------------------------ + // Operators + // ------------------------------------------------------------------------ + + /** + * Parse the content into fields. By default, a single field (the raw + * content) is returned. + * Should be overridden. + */ + protected void parseContent() { + fFields = new Object[1]; + fFields[0] = fRawContent; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + ((fParentEvent != null) ? fParentEvent.hashCode() : 0); + result = 37 * result + ((fRawContent != null) ? fRawContent.hashCode() : 0); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEventContent)) + return false; + TmfEventContent o = (TmfEventContent) other; + return fRawContent.equals(o.fRawContent); + } + + @Override + public String toString() { + Object[] fields = getFields(); + StringBuilder result = new StringBuilder("[TmfEventContent("); + for (int i = 0; i < fields.length; i++) { + if (i > 0) result.append(","); + result.append(fields[i]); + } + result.append(")]"); + return result.toString(); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventField.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventField.java new file mode 100644 index 0000000000..e39180fe34 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventField.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfEventField + *

+ * A basic event field. + * + * TODO: Add support for field hierarchy. + */ +public class TmfEventField { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfEventContent fParent; + private final String fFieldId; + private Object fValue; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + @SuppressWarnings("unused") + private TmfEventField() { + throw new AssertionError(); + } + + /** + * @param parent + * @param id + * @param value + */ + public TmfEventField(TmfEventContent parent, String id, Object value) { + if (id == null) { + throw new IllegalArgumentException(); + } + fParent = parent; + fFieldId = id; + fValue = value; + } + + /** + * @param other + */ + public TmfEventField(TmfEventField other) { + if (other == null) + throw new IllegalArgumentException(); + fParent = other.fParent; + fFieldId = other.fFieldId; + fValue = other.fValue; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public TmfEventContent getParent() { + return fParent; + } + + /** + * @return + */ + public String getId() { + return fFieldId; + } + + /** + * @return + */ + public Object getValue() { + return fValue; + } + + /** + * @param value new field value + */ + protected void setValue(Object value) { + fValue = value; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + fFieldId.hashCode(); + result = 37 * result + fValue.hashCode(); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEventField)) + return false; + TmfEventField o = (TmfEventField) other; + return fParent.equals(o.fParent) && fFieldId.equals(o.fFieldId) && fValue.equals(o.fValue); + } + + @Override + public String toString() { + return "[TmfEventField(" + fFieldId + ":" + fValue.toString() + ")]"; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventReference.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventReference.java new file mode 100644 index 0000000000..39b319e4dc --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventReference.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfEventReference + *

+ * An application-defined event reference. + */ +public class TmfEventReference { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected Object fReference; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * The default constructor + */ + public TmfEventReference() { + fReference = null; + } + + /** + * @param reference the event reference + */ + public TmfEventReference(Object reference) { + fReference = reference; + } + + /** + * Copy constructor + * @param other the original event reference + */ + public TmfEventReference(TmfEventReference other) { + if (other == null) + throw new IllegalArgumentException(); + TmfEventReference o = (TmfEventReference) other; + fReference = o.fReference; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the event reference + */ + public Object getReference() { + return fReference; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + return (fReference != null) ? fReference.hashCode() : 0; + } + + @Override + public String toString() { + return "[TmfEventReference(" + ((fReference != null) ? fReference.toString() : "null") + ")]"; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEventReference)) + return false; + TmfEventReference o = (TmfEventReference) other; + return fReference.equals(o.fReference); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventSource.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventSource.java new file mode 100644 index 0000000000..3a351fbc4f --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventSource.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfEventSource + *

+ * The event source. + */ +public class TmfEventSource { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected Object fSourceId; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * The default constructor + */ + public TmfEventSource() { + fSourceId = null; + } + + /** + * @param sourceId + */ + public TmfEventSource(Object sourceId) { + fSourceId = sourceId; + } + + /** + * Copy constructor + * @param other + */ + public TmfEventSource(TmfEventSource other) { + if (other == null) + throw new IllegalArgumentException(); + TmfEventSource o = (TmfEventSource) other; + fSourceId = o.fSourceId; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public Object getSourceId() { + return fSourceId; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + return (fSourceId != null) ? fSourceId.hashCode() : 0; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEventSource)) + return false; + TmfEventSource o = (TmfEventSource) other; + return fSourceId.equals(o.fSourceId); + } + + @Override + public String toString() { + return "[TmfEventSource(" + ((fSourceId != null) ? fSourceId.toString() : "null") + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventType.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventType.java new file mode 100644 index 0000000000..fa998eca2d --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfEventType.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +import java.util.HashMap; +import java.util.Map; + +/** + * TmfEventType + *

+ * The event type. + */ +public class TmfEventType { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + public static final String DEFAULT_TYPE_ID = "TMF Default Type"; + public static final String[] DEFAULT_LABELS = new String[] { "Content" }; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final String fTypeId; + private final String[] fFieldLabels; + private final int fNbFields; + private final Map fFieldMap; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Default constructor + */ + public TmfEventType() { + this(DEFAULT_TYPE_ID, DEFAULT_LABELS); + } + + /** + * @param type + * @param format + */ + public TmfEventType(String typeId, String[] labels) { + if (typeId == null || labels == null) + throw new IllegalArgumentException(); + fTypeId = typeId; + fFieldLabels = labels; + fNbFields = fFieldLabels.length; + fFieldMap = new HashMap(); + for (int i = 0; i < fNbFields; i++) { + fFieldMap.put(fFieldLabels[i], i); + } + } + + /** + * Copy constructor + * @param other + */ + public TmfEventType(TmfEventType other) { + if (other == null) + throw new IllegalArgumentException(); + fTypeId = other.fTypeId; + fFieldLabels = other.fFieldLabels; + fNbFields = other.fNbFields; + fFieldMap = other.fFieldMap; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public String getTypeId() { + return fTypeId; + } + + /** + * @return + */ + public int getNbFields() { + return fNbFields; + } + + /** + * @return + */ + public int getFieldIndex(String id) throws TmfNoSuchFieldException { + Integer index = fFieldMap.get(id); + if (index == null) + throw(new TmfNoSuchFieldException(id)); + return index; + } + + /** + * @return + */ + public String[] getLabels() { + return fFieldLabels; + } + + /** + * @return + */ + public String getLabel(int i) throws TmfNoSuchFieldException { + if (i >= 0 && i < fNbFields) + return fFieldLabels[i]; + throw new TmfNoSuchFieldException("Bad index (" + i + ")"); + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + return fTypeId.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfEventType)) + return false; + TmfEventType o = (TmfEventType) other; + return fTypeId.equals(o.fTypeId); + } + + @Override + public String toString() { + return "[TmfEventType:" + fTypeId + "]"; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfNoSuchFieldException.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfNoSuchFieldException.java new file mode 100644 index 0000000000..e28e933eaa --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfNoSuchFieldException.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfNoSuchFieldException + *

+ * TODO: Implement me. Please. + */ +public class TmfNoSuchFieldException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 2504826473032522133L; + + public TmfNoSuchFieldException(String message) { + super(message); + } +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimeRange.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimeRange.java new file mode 100644 index 0000000000..014bd828e6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimeRange.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfTimeRange + *

+ * A utility class to define time ranges. + */ +public class TmfTimeRange { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + public static final TmfTimeRange Eternity = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigCrunch); + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfTimestamp fStartTime; + private final TmfTimestamp fEndTime; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + @SuppressWarnings("unused") + private TmfTimeRange() { + throw new AssertionError(); + } + + /** + * @param startTime + * @param endTime + */ + public TmfTimeRange(TmfTimestamp startTime, TmfTimestamp endTime) { + if (startTime == null || endTime == null) { + throw new IllegalArgumentException(); + } + fStartTime = new TmfTimestamp(startTime); + fEndTime = new TmfTimestamp(endTime); + } + + /** + * Copy constructor + * @param other + */ + public TmfTimeRange(TmfTimeRange other) { + if (other == null) { + throw new IllegalArgumentException(); + } + fStartTime = new TmfTimestamp(other.fStartTime); + fEndTime = new TmfTimestamp(other.fEndTime); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return The time range start time + */ + public TmfTimestamp getStartTime() { + return new TmfTimestamp(fStartTime); + } + + /** + * @return The time range end time + */ + public TmfTimestamp getEndTime() { + return new TmfTimestamp(fEndTime); + } + + // ------------------------------------------------------------------------ + // Predicates + // ------------------------------------------------------------------------ + + /** + * Check if the timestamp is within the time range + * + * @param ts + * @return + */ + public boolean contains(TmfTimestamp ts) { + return (fStartTime.compareTo(ts, true) <= 0) && (fEndTime.compareTo(ts, true) >= 0); + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + fStartTime.hashCode(); + result = 37 * result + fEndTime.hashCode(); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfTimeRange)) + return false; + TmfTimeRange range = (TmfTimeRange) other; + return range.fStartTime.equals(fStartTime) && range.fEndTime.equals(fEndTime); + } + + @Override + public String toString() { + return "[TmfTimeRange(" + fStartTime + ":" + fEndTime + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimestamp.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimestamp.java new file mode 100644 index 0000000000..d3a0b76dce --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTimestamp.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + + +/** + * TmfTimestamp + *

+ * The fundamental time reference in the TMF. + *

+ * It provides a generic timestamp implementation in its most basic form: + *

+ * Where: + * + * In short: + * + * To allow synchronization of timestamps from different reference clocks, + * there is a possibility to "adjust" the timestamp by changing its scale + * (traces of different time scale) and/or by adding an offset to its value + * (clock drift between traces). + *

+ * Notice that the adjusted timestamp value could be negative e.g. for events + * that occurred before t0 wrt the reference clock. + */ +public class TmfTimestamp implements Cloneable { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected long fValue; // The timestamp raw value + protected byte fScale; // The time scale + protected long fPrecision; // The value precision (tolerance) + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + // The beginning and end of time + public static final TmfTimestamp BigBang = new TmfTimestamp(Long.MIN_VALUE, Byte.MAX_VALUE, 0); + public static final TmfTimestamp BigCrunch = new TmfTimestamp(Long.MAX_VALUE, Byte.MAX_VALUE, 0); + public static final TmfTimestamp Zero = new TmfTimestamp(0, (byte) 0, 0); + + /* + * A java long has a maximum of 19 significant digits. + * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807) + * + * It is therefore useless to try to synchronize 2 timestamps whose + * difference in scale exceeds that value. + */ + private int MAX_SCALING = 19; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Default constructor + */ + public TmfTimestamp() { + this(0, (byte) 0, 0); + } + + /** + * Simple constructor with value only + */ + public TmfTimestamp(long value) { + this(value, (byte) 0, 0); + } + + /** + * Simple constructor with value and scale + * + * @param value + * @param scale + */ + public TmfTimestamp(long value, byte scale) { + this(value, scale, 0); + } + + /** + * Constructor with value, scale and precision + * + * @param value + * @param scale + * @param precision + */ + public TmfTimestamp(long value, byte scale, long precision) { + fValue = value; + fScale = scale; + fPrecision = Math.abs(precision); + } + + /** + * Copy constructor + * + * @param other + */ + public TmfTimestamp(TmfTimestamp other) { + if (other == null) + throw new IllegalArgumentException(); + fValue = other.fValue; + fScale = other.fScale; + fPrecision = other.fPrecision; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the timestamp value + */ + public long getValue() { + return fValue; + } + + /** + * @return the timestamp scale + */ + public byte getScale() { + return fScale; + } + + /** + * @return the timestamp value precision + */ + public long getPrecision() { + return fPrecision; + } + + // ------------------------------------------------------------------------ + // Operators + // ------------------------------------------------------------------------ + + /** + * Return a shifted and scaled timestamp. + * + * Limitation: The scaling is limited to MAX_SCALING orders of magnitude. + * The main reason is that the 64 bits value starts to lose any significance + * meaning beyond that scale difference and it's not even worth the trouble + * to switch to BigDecimal arithmetics. + * + * @param offset the shift value (in the same scale as newScale) + * @param newScale the new timestamp scale + * @return the synchronized timestamp in the new scale + * @throws ArithmeticException + */ + public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException { + + long newValue = fValue; + long newPrecision = fPrecision; + + // Determine the scaling factor + if (fScale != newScale) { + int scaleDiff = Math.abs(fScale - newScale); + // Let's try to be realistic... + if (scaleDiff > MAX_SCALING) { + throw new ArithmeticException("Scaling exception"); + } + // Not pretty... + long scalingFactor = 1; + for (int i = 0; i < scaleDiff; i++) { + scalingFactor *= 10; + } + if (newScale < fScale) { + newValue *= scalingFactor; + newPrecision *= scalingFactor; + } else { + newValue /= scalingFactor; + newPrecision /= scalingFactor; + } + } + + return new TmfTimestamp(newValue + offset, newScale, newPrecision); + } + + /** + * Compute the adjustment, in the reference scale, needed to synchronize + * this timestamp with a reference timestamp. + * + * @param reference the reference timestamp to synchronize with + * @param scale the scale of the adjustment + * @return the adjustment term in the reference time scale + * @throws ArithmeticException + */ + public long getAdjustment(TmfTimestamp reference, byte scale) throws ArithmeticException { + TmfTimestamp ts1 = synchronize(0, scale); + TmfTimestamp ts2 = reference.synchronize(0, scale); + return ts2.fValue - ts1.fValue; + } + + /** + * Compare with another timestamp + * + * @param other the other timestamp + * @param withinPrecision indicates if precision is to be take into consideration + * @return -1: this timestamp is lower (i.e. anterior) + * 0: timestamps are equal (within precision if requested) + * 1: this timestamp is higher (i.e. posterior) + */ + public int compareTo(final TmfTimestamp other, boolean withinPrecision) { + + // If values have the same time scale, perform the comparison + if (fScale == other.fScale) { + if (withinPrecision) { + if ((fValue + fPrecision) < (other.fValue - other.fPrecision)) + return -1; + if ((fValue - fPrecision) > (other.fValue + other.fPrecision)) + return 1; + return 0; + } + return (fValue == other.fValue) ? 0 : (fValue < other.fValue) ? -1 : 1; + } + + // If values have different time scales, adjust to the finest one and + // then compare. If the scaling difference is too large, revert to + // some heuristics. Hopefully, nobody will try to compare galactic and + // quantic clock events... + if (Math.abs(fScale - other.fScale) > MAX_SCALING) { + return simpleCompare(other); + } + + byte newScale = (fScale < other.fScale) ? fScale : other.fScale; + try { + TmfTimestamp ts1 = this.synchronize(0, newScale); + TmfTimestamp ts2 = other.synchronize(0, newScale); + return ts1.compareTo(ts2, withinPrecision); + } catch (ArithmeticException e) { + return simpleCompare(other); + } + } + + private int simpleCompare(final TmfTimestamp other) { + if ((fValue == 0) || (other.fValue == 0)) { + return (fValue == other.fValue) ? 0 + : (fValue < other.fValue) ? -1 : 1; + } + if ((fValue > 0) && (other.fValue > 0)) { + return (fScale < other.fScale) ? -1 : 1; + } + if ((fValue < 0) && (other.fValue < 0)) { + return (fScale > other.fScale) ? -1 : 1; + } + return (fValue < 0) ? -1 : 1; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + (int) (fValue ^ (fValue >>> 32)); + result = 37 * result + fScale; + result = 37 * result + (int) (fPrecision ^ (fPrecision >>> 32)); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfTimestamp)) + return false; + TmfTimestamp o = (TmfTimestamp) other; + return compareTo(o, false) == 0; + } + + @Override + public String toString() { + return "[TmfTimestamp(" + fValue + "," + fScale + "," + fPrecision + ")]"; + } + + @Override + public TmfTimestamp clone() { + TmfTimestamp clone = null; + try { + clone = (TmfTimestamp) super.clone(); + clone.fValue = fValue; + clone.fScale = fScale; + clone.fPrecision = fPrecision; + } catch (CloneNotSupportedException e) { + } + return clone; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTraceEvent.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTraceEvent.java new file mode 100644 index 0000000000..26759e2459 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/event/TmfTraceEvent.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.event; + +/** + * TmfTraceEvent + *

+ * A trace event associates a source code line to an event. The intent is to + * provide the capability to open an editor at the line of code that produced + * the event. + *

+ * TODO: Concept is still a bit vague and should be aligned with the CDT + * source lookup service. + * TODO: Consider composition instead of extension + */ +public class TmfTraceEvent extends TmfEvent { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final String fSourcePath; + private final String fFileName; + private final int fLineNumber; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param originalTS + * @param effectiveTS + * @param source + * @param type + * @param content + * @param reference + * @param path + * @param file + * @param line + */ + public TmfTraceEvent(TmfTimestamp originalTS, TmfTimestamp effectiveTS, TmfEventSource source, + TmfEventType type, TmfEventReference reference, String path, String file, int line) + { + super(originalTS, effectiveTS, source, type, reference); + fSourcePath = path; + fFileName = file; + fLineNumber = line; + } + + /** + * @param timestamp + * @param source + * @param type + * @param content + * @param reference + * @param path + * @param file + * @param line + */ + public TmfTraceEvent(TmfTimestamp timestamp, TmfEventSource source, TmfEventType type, + TmfEventReference reference, String path, String file, int line) + { + super(timestamp, source, type, reference); + fSourcePath = path; + fFileName = file; + fLineNumber = line; + } + + /** + * @param other + */ + public TmfTraceEvent(TmfTraceEvent other) { + super(other); + fSourcePath = other.fSourcePath; + fFileName = other.fFileName; + fLineNumber = other.fLineNumber; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public String getSourcePath() { + return fSourcePath; + } + + /** + * @return + */ + public String getFileName() { + return fFileName; + } + + /** + * @return + */ + public int getLineNumber() { + return fLineNumber; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 37 * result + ((fSourcePath != null) ? fSourcePath.hashCode() : 0); + result = 37 * result + ((fFileName != null) ? fFileName.hashCode() : 0); + result = 37 * result + fLineNumber; + return result; + } + + @Override + public boolean equals(Object other) { + if (other instanceof TmfEvent) { + return super.equals(other); + } + if (!(other instanceof TmfTraceEvent)) { + return false; + } + TmfTraceEvent o = (TmfTraceEvent) other; + return super.equals((TmfEvent) o) && fSourcePath.equals(o.fSourcePath) && + fFileName.equals(o.fFileName) && fLineNumber == o.fLineNumber; + + } + + // TODO: Proper format + @Override + public String toString() { + return "[TmfTraceEvent(" + fSourcePath + "," + fFileName + "," + fLineNumber + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperiment.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperiment.java new file mode 100644 index 0000000000..47a2c7c2df --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperiment.java @@ -0,0 +1,682 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.experiment; + +import java.util.Collections; +import java.util.Vector; + +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.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.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +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; + +/** + * TmfExperiment + *

+ * TmfExperiment presents a time-ordered, unified view of a set of TmfTraces + * that are part of a tracing experiment. + *

+ */ +public class TmfExperiment extends TmfEventProvider implements ITmfTrace { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + // The currently selected experiment + private static TmfExperiment fCurrentExperiment = null; + + // The set of traces that constitute the experiment + private ITmfTrace[] fTraces; + + // The total number of events + private long fNbEvents; + + // The experiment time range + private TmfTimeRange fTimeRange; + + // The experiment reference timestamp (default: BigBang) + private TmfTimestamp fEpoch; + + // The experiment index + private Vector fCheckpoints = new Vector(); + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param type + * @param id + * @param traces + * @param epoch + * @param indexPageSize + */ + public TmfExperiment(Class type, String id, ITmfTrace[] traces, TmfTimestamp epoch, int indexPageSize) { + super(id, type); + + fTraces = traces; + fEpoch = epoch; + fIndexPageSize = indexPageSize; + + updateNbEvents(); + updateTimeRange(); + } + + /** + * @param type + * @param id + * @param traces + */ + public TmfExperiment(Class type, String id, ITmfTrace[] traces) { + this(type, id, traces, TmfTimestamp.Zero, DEFAULT_INDEX_PAGE_SIZE); + } + + /** + * @param type + * @param id + * @param traces + * @param indexPageSize + */ + public TmfExperiment(Class type, String id, ITmfTrace[] traces, int indexPageSize) { + this(type, id, traces, TmfTimestamp.Zero, indexPageSize); + } + + + public TmfExperiment(TmfExperiment other) { + super(other.getName(), other.fType); + + 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].createTraceCopy(); + } + + fNbEvents = other.fNbEvents; + fTimeRange = other.fTimeRange; + } + + public TmfExperiment createTraceCopy() { + return new TmfExperiment(this); + } + + /** + * Clears the experiment + */ + @Override + public void dispose() { + for (ITmfTrace trace : fTraces) { + trace.dispose(); + } + fTraces = null; + fCheckpoints.clear(); + super.dispose(); + } + + private static void setCurrentExperiment(TmfExperiment experiment) { + fCurrentExperiment = experiment; + } + + // ------------------------------------------------------------------------ + // ITmfTrace + // ------------------------------------------------------------------------ + + public String getPath() { + return null; + } + + public long getNbEvents() { + return fNbEvents; + } + + public int getCacheSize() { + return fIndexPageSize; + } + + public TmfTimeRange getTimeRange() { + return fTimeRange; + } + + public TmfTimestamp getStartTime() { + return fTimeRange.getStartTime(); + } + + public TmfTimestamp getEndTime() { + return fTimeRange.getEndTime(); + } + + public Vector getCheckpoints() { + return fCheckpoints; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + public static TmfExperiment getCurrentExperiment() { + return fCurrentExperiment; + } + + public TmfTimestamp getEpoch() { + return fEpoch; + } + + public ITmfTrace[] 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 timestamp + * @return + */ + 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. + * + * @param index + * @return + */ + public TmfTimestamp getTimestamp(int index) { + TmfExperimentContext context = seekEvent(index); + TmfEvent event = getNextEvent(context); + return (event != null) ? event.getTimestamp() : null; + } + + // ------------------------------------------------------------------------ + // Operators + // ------------------------------------------------------------------------ + + /** + * 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) { + if (trace.getNbEvents() > 0) { + 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 request) { + TmfTimestamp timestamp = (request instanceof ITmfEventRequest) ? + ((ITmfEventRequest) 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; + } + + // ------------------------------------------------------------------------ + // ITmfTrace trace positioning + // ------------------------------------------------------------------------ + + // Returns a brand new context based on the location provided + // and initializes the event queues + public TmfExperimentContext seekLocation(ITmfLocation location) { + + // Validate the location + if (location != null && !(location instanceof TmfExperimentLocation)) { + return null; // Throw an exception? + } + + // Instantiate the location + TmfExperimentLocation expLocation = (location == null) + ? new TmfExperimentLocation(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]); + long rank = 0; + for (int i = 0; i < fTraces.length; i++) { + // Get the relevant trace attributes + ITmfLocation traceLocation = expLocation.getLocation()[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()[i] = context.getContexts()[i].getLocation(); + context.getEvents()[i] = fTraces[i].getNextEvent(context.getContexts()[i]); + } + + // Finalize context + context.setLocation(expLocation); + context.setRank(rank); + context.setLastTrace(TmfExperimentContext.NO_TRACE); + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp) + */ + 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)); + + // 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 + TmfExperimentContext nextEventContext = new TmfExperimentContext(context); + TmfEvent event = getNextEvent(nextEventContext); + while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { + context = new TmfExperimentContext(nextEventContext); + event = getNextEvent(nextEventContext); + } + context.setLastTrace(TmfExperimentContext.NO_TRACE); + + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(long) + */ + public TmfExperimentContext seekEvent(long rank) { + + // 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); + long pos = (long) index * fIndexPageSize; + context.setRank(pos); + + // And locate the event + TmfExperimentContext nextEventContext = new TmfExperimentContext(context); + TmfEvent event = getNextEvent(nextEventContext); + while (event != null && pos++ < rank) { + event = getNextEvent(nextEventContext); + context = new TmfExperimentContext(nextEventContext); + if (event != null) context.updateRank(-1); + } + context.setLastTrace(TmfExperimentContext.NO_TRACE); + + return context; + } + + /** + * Scan the next events from all traces and return the next one + * in chronological order. + * + * @param context + * @return + */ + public synchronized TmfEvent getNextEvent(TmfContext context) { + + // Validate the context + if (!(context instanceof TmfExperimentContext)) { + return null; // Throw an exception? + } + + 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); + } + + // 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; + } + } + } + + // Update the experiment context and set the "next" event + TmfEvent event = null; + if (trace >= 0) { + expContext.setLastTrace(trace); + expContext.updateRank(1); + TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation(); + TmfContext traceContext = expContext.getContexts()[trace]; + expLocation.getLocation()[trace] = traceContext.getLocation().clone(); + expLocation.getRanks()[trace] = traceContext.getRank(); + event = expContext.getEvents()[trace]; + } + + return event; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#parseEvent(org.eclipse.linuxtools.tmf.trace.TmfContext) + */ + public TmfEvent parseEvent(TmfContext context) { + + if (context instanceof TmfExperimentContext) { + TmfExperimentContext expContext = (TmfExperimentContext) context; + int lastTrace = expContext.getLastTrace(); + if (lastTrace != -1) { + TmfContext traceContext = expContext.getContexts()[lastTrace]; + expContext.getEvents()[lastTrace] = expContext.getTraces()[lastTrace].getNextEvent(traceContext); + expContext.updateRank(1); + TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation(); + expLocation.getLocation()[lastTrace] = traceContext.getLocation().clone(); + } + + int trace = -1; + TmfTimestamp timestamp = TmfTimestamp.BigCrunch; + for (int i = 0; i < expContext.getTraces().length; i++) { + if (expContext.getEvents()[i] != null) { + if (expContext.getEvents()[i].getTimestamp() != null) { + TmfTimestamp otherTS = expContext.getEvents()[i].getTimestamp(); + if (otherTS.compareTo(timestamp, true) < 0) { + trace = i; + timestamp = otherTS; + } + } + } + } + if (trace >= 0) { + expContext.setLastTrace(TmfExperimentContext.NO_TRACE); + return expContext.getEvents()[trace]; + } + } + + return null; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + 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(this) { + 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(new TmfExperiment(this)); + job.schedule(); + + if (waitForCompletion) { + try { + job.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private class IndexingJob extends Job { + + private final String experimentId; + private final ITmfTrace[] traces; + private Vector checkpoints; + + public IndexingJob(TmfExperiment experiment) { + super(experiment.getName()); + experimentId = experiment.getName(); + traces = experiment.getTraces(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected IStatus run(IProgressMonitor monitor) { + + // Minimal check + if (traces.length == 0) { + fIndexing = false; + return Status.OK_STATUS; + } + + monitor.beginTask("Indexing " + experimentId, IProgressMonitor.UNKNOWN); + + int nbEvents = 0; + TmfTimestamp startTime = null; + TmfTimestamp lastTime = null; + + // Reset the index + checkpoints = new Vector(); + + try { + // Position the trace at the beginning + TmfExperimentContext context = seekLocation(null); + TmfExperimentLocation location = (TmfExperimentLocation) context.getLocation().clone(); + + // 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) { + checkpoints.add(new TmfCheckpoint(lastTime, location)); + + monitor.worked(1); + + // Check monitor *after* fCheckpoints has been updated + if (monitor.isCanceled()) { + monitor.done(); + return Status.CANCEL_STATUS; + } + } + + // We will need the contexts at the next iteration + if ((nbEvents % fIndexPageSize) == 0) { + location = (TmfExperimentLocation) context.getLocation().clone(); + } + + event = getNextEvent(context); + } + + } + finally { + synchronized(this) { + fCheckpoints = checkpoints; + fNbEvents = nbEvents; + fTimeRange = new TmfTimeRange(startTime, lastTime); + fIndexing = false; + fIndexed = true; + } +// notifyListeners(fTimeRange); + monitor.done(); + } + + return Status.OK_STATUS; + } + } + + protected void notifyListeners(TmfTimeRange range) { + broadcast(new TmfRangeSynchSignal(this, range, range.getStartTime())); + } + + // ------------------------------------------------------------------------ + // Signal handlers + // ------------------------------------------------------------------------ + + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + TmfExperiment experiment = signal.getExperiment(); + if (experiment == this) { + setCurrentExperiment(experiment); + } + else { + dispose(); + } +// if (signal.getExperiment() == this) { +// indexExperiment(true); +// } + } + + @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())); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentCheckpoint.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentCheckpoint.java new file mode 100644 index 0000000000..f93ccb4f19 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentCheckpoint.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.experiment; + +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.trace.TmfContext; + +/** + * TmfExperimentCheckpoint + *

+ * TODO: Implement me. Please. + */ +public class TmfExperimentCheckpoint implements Comparable { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfTimestamp fTimestamp; + private final TmfContext[] fContexts; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param ts + * @param location + */ + public TmfExperimentCheckpoint(TmfTimestamp ts, TmfContext[] contexts) { + fTimestamp = ts; + fContexts = contexts; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the checkpoint event timestamp + */ + public TmfTimestamp getTimestamp() { + return fTimestamp; + } + + /** + * @return the checkpoint event stream location + */ + public TmfContext[] getContexts() { + return fContexts; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 37; + result = 17 * result + fTimestamp.hashCode(); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfExperimentCheckpoint)) { + return false; + } + TmfExperimentCheckpoint o = (TmfExperimentCheckpoint) other; + return fTimestamp.equals(o.fTimestamp); + } + + // ------------------------------------------------------------------------ + // Comparable + // ------------------------------------------------------------------------ + + public int compareTo(TmfExperimentCheckpoint other) { + return fTimestamp.compareTo(other.fTimestamp, false); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentContext.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentContext.java new file mode 100644 index 0000000000..6814225db8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentContext.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.experiment; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.trace.ITmfLocation; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.trace.TmfContext; + +/** + * TmfExperimentContext + *

+ * The experiment keeps track of the next event from each of its traces so + * it can pick the next one in chronological order. + *

+ * This implies that the "next" event from each trace has already been + * read and that we at least know its timestamp. This doesn't imply that a + * full parse of the event content was performed (read: LTTng works like + * this). + *

+ * The last trace refers to the trace from which the last event was + * "consumed" at the experiment level. + */ +public class TmfExperimentContext extends TmfContext { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + public static final int NO_TRACE = -1; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private ITmfTrace[] fTraces = new ITmfTrace[0]; + private TmfContext[] fContexts; + private TmfEvent[] fEvents; + private int lastTrace; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public TmfExperimentContext(ITmfTrace[] traces, TmfContext[] contexts) { + super(); + fTraces = traces; + fContexts = contexts; + fEvents = new TmfEvent[fTraces.length]; + + ITmfLocation[] locations = new ITmfLocation[fTraces.length]; + long[] ranks = new long[fTraces.length]; + long rank = 0; + for (int i = 0; i < fTraces.length; i++) { + if (contexts[i] != null) { + locations[i] = contexts[i].getLocation(); + ranks[i] = contexts[i].getRank(); + rank += contexts[i].getRank(); + } + } + + setLocation(new TmfExperimentLocation(locations, ranks)); + setRank(rank); + lastTrace = NO_TRACE; + } + + public TmfExperimentContext(ITmfTrace[] traces) { + this(traces, new TmfContext[traces.length]); + } + + public TmfExperimentContext(TmfExperimentContext other) { + this(other.fTraces, other.cloneContexts()); + fEvents = other.fEvents; + setLocation(other.getLocation().clone()); + setRank(other.getRank()); + setLastTrace(other.lastTrace); + } + + private TmfContext[] cloneContexts() { + TmfContext[] contexts = new TmfContext[fContexts.length]; + for (int i = 0; i < fContexts.length; i++) + contexts[i] = fContexts[i].clone(); + return contexts; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + public ITmfTrace[] getTraces() { + return fTraces; + } + + public TmfContext[] getContexts() { + return fContexts; + } + + public TmfEvent[] getEvents() { + return fEvents; + } + + public int getLastTrace() { + return lastTrace; + } + + public void setLastTrace(int newIndex) { + lastTrace = newIndex; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentLocation.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentLocation.java new file mode 100644 index 0000000000..712cc08bcf --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/experiment/TmfExperimentLocation.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.experiment; + +import org.eclipse.linuxtools.tmf.trace.ITmfLocation; +import org.eclipse.linuxtools.tmf.trace.TmfLocation; + +/** + * TmfExperimentLocation + *

+ * The experiment location is the set of its traces' locations. + */ +public class TmfExperimentLocation extends TmfLocation[]> { + + private long[] fRanks; + + public TmfExperimentLocation(ITmfLocation[] locations, long[] ranks) { + super(locations); + fRanks = ranks; + } + + @Override + public TmfExperimentLocation clone() { + super.clone(); // To keep FindBugs happy + ITmfLocation[] locations = (ITmfLocation[]) getLocation(); + ITmfLocation[] clones = new ITmfLocation[locations.length]; + for (int i = 0; i < locations.length; i++) { + clones[i] = locations[i].clone(); + } + return new TmfExperimentLocation(clones, fRanks.clone()); + } + + public long[] getRanks() { + return fRanks; + } +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/parser/ITmfEventParser.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/parser/ITmfEventParser.java new file mode 100644 index 0000000000..fc6e699f90 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/parser/ITmfEventParser.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.parser; + +import java.io.IOException; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.trace.TmfContext; + +/** + * ITmfEventParser + *

+ * TODO: Implement me. Please. + */ +public interface ITmfEventParser { + + /** + * @return + * @throws IOException + */ + public TmfEvent parseNextEvent(ITmfTrace stream, TmfContext context) throws IOException; +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfDataRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfDataRequest.java new file mode 100644 index 0000000000..7beecac7c6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfDataRequest.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import org.eclipse.linuxtools.tmf.event.TmfData; + +/** + * ITmfDataRequest + *

+ * TODO: Implement me. Please. + */ +public interface ITmfDataRequest { + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return request data type (T) + */ + public Class getDataType(); + + /** + * @return request ID + */ + public int getRequestId(); + + /** + * @return the index of the first event requested + */ + public int getIndex(); + + /** + * @return the number of requested events + */ + public int getNbRequested(); + + /** + * @return the block size + */ + public int getBlockize(); + + /** + * @return the number of events read so far + */ + public int getNbRead(); + + // ------------------------------------------------------------------------ + // Request state + // ------------------------------------------------------------------------ + + public boolean isCompleted(); + public boolean isFailed(); + public boolean isCancelled(); + + // ------------------------------------------------------------------------ + // Data handling + // ------------------------------------------------------------------------ + + public void setData(T[] data); + public T[] getData(); + public void handleData(); + + // ------------------------------------------------------------------------ + // Request handling + // ------------------------------------------------------------------------ + + public void handleCompleted(); + public void handleSuccess(); + public void handleFailure(); + public void handleCancel(); + + /** + * To suspend the client thread until the request completes + * (or is canceled). + */ + public void waitForCompletion() throws InterruptedException; + + // ------------------------------------------------------------------------ + // Request state modifiers + // ------------------------------------------------------------------------ + + public void done(); + public void fail(); + public void cancel(); +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfEventRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfEventRequest.java new file mode 100644 index 0000000000..9f14f3e084 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/ITmfEventRequest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * ITmfEventRequest + *

+ * TODO: Implement me. Please. + */ +public interface ITmfEventRequest extends ITmfDataRequest { + + /** + * @return the requested time range + */ + public TmfTimeRange getRange(); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedDataRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedDataRequest.java new file mode 100644 index 0000000000..957b1aee5f --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedDataRequest.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import java.util.Vector; + +import org.eclipse.linuxtools.tmf.event.TmfData; + +/** + * TmfCoalescedDataRequest + *

+ * TODO: Implement me. Please. + */ +public class TmfCoalescedDataRequest extends TmfDataRequest { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + protected Vector> fRequests = new Vector>(); + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Default constructor + */ + public TmfCoalescedDataRequest(Class dataType) { + this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param nbRequested + */ + public TmfCoalescedDataRequest(Class dataType, int index) { + this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param index + * @param nbRequested + */ + public TmfCoalescedDataRequest(Class dataType, int index, int nbRequested) { + this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE); + } + + /** + * @param index + * @param nbRequested + * @param blockSize + */ + public TmfCoalescedDataRequest(Class dataType, int index, int nbRequested, int blockSize) { + super(dataType, index, nbRequested, blockSize); + } + + // ------------------------------------------------------------------------ + // Management + // ------------------------------------------------------------------------ + + public void addRequest(ITmfDataRequest request) { + fRequests.add(request); + } + + public boolean isCompatible(ITmfDataRequest request) { + + boolean ok = request.getIndex() == getIndex(); + ok &= request.getNbRequested() == getNbRequested(); + ok &= request.getBlockize() == getBlockize(); + + return ok; + } + + // ------------------------------------------------------------------------ + // ITmfDataRequest + // ------------------------------------------------------------------------ + + @Override + public void handleData() { + for (ITmfDataRequest request : fRequests) { + request.setData(getData()); + request.handleData(); + } + } + + @Override + public void done() { + for (ITmfDataRequest request : fRequests) { + request.done(); + } + super.done(); + } + + @Override + public void fail() { + for (ITmfDataRequest request : fRequests) { + request.fail(); + } + super.fail(); + } + + @Override + public void cancel() { + for (ITmfDataRequest request : fRequests) { + request.cancel(); + } + super.cancel(); + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + // All requests have a unique id + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TmfCoalescedDataRequest) { + TmfCoalescedDataRequest request = (TmfCoalescedDataRequest) other; + return (request.getDataType() == getDataType()) && + (request.getIndex() == getIndex()) && + (request.getNbRequested() == getNbRequested()); + } + return false; + } + + @Override + public String toString() { + return "[TmfCoalescedDataRequest(" + getRequestId() + "," + getDataType().getSimpleName() + + "," + getIndex() + "," + getNbRequested() + "," + getBlockize() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedEventRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedEventRequest.java new file mode 100644 index 0000000000..0bcd53037c --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfCoalescedEventRequest.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * TmfCoalescedEventRequest + *

+ * TODO: Implement me. Please. + */ +public class TmfCoalescedEventRequest extends TmfCoalescedDataRequest implements ITmfEventRequest { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfTimeRange fRange; // The requested events time range + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * @param range + */ + public TmfCoalescedEventRequest(Class dataType) { + this(dataType, TmfTimeRange.Eternity, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + */ + public TmfCoalescedEventRequest(Class dataType, TmfTimeRange range) { + this(dataType, range, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + * @param nbRequested + */ + public TmfCoalescedEventRequest(Class dataType, TmfTimeRange range, int nbRequested) { + this(dataType, range, nbRequested, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + * @param nbRequested + * @param blockSize Size of the largest blocks expected + */ + public TmfCoalescedEventRequest(Class dataType, TmfTimeRange range, int nbRequested, int blockSize) { + super(dataType, 0, nbRequested, blockSize); + fRange = range; + } + + // ------------------------------------------------------------------------ + // Management + // ------------------------------------------------------------------------ + + @Override + public boolean isCompatible(ITmfDataRequest request) { + if (request instanceof ITmfEventRequest) { + boolean ok = getNbRequested() == request.getNbRequested(); + ok &= getBlockize() == request.getBlockize(); + ok &= fRange.equals(((ITmfEventRequest) request).getRange()); + return ok; + } + return false; + } + + // ------------------------------------------------------------------------ + // ITmfEventRequest + // ------------------------------------------------------------------------ + + public TmfTimeRange getRange() { + return fRange; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + // All requests have a unique id + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TmfCoalescedEventRequest) { + TmfCoalescedEventRequest request = (TmfCoalescedEventRequest) other; + return (request.getDataType() == getDataType()) && + (request.getIndex() == getIndex()) && + (request.getNbRequested() == getNbRequested()) && + (request.getRange().equals(getRange())); + } + if (other instanceof TmfCoalescedDataRequest) { + return super.equals(other); + } + return false; + } + + @Override + public String toString() { + return "[TmfCoalescedEventRequest(" + getRequestId() + "," + getDataType().getSimpleName() + + "," + getRange() + "," + getNbRequested() + "," + getBlockize() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfDataRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfDataRequest.java new file mode 100644 index 0000000000..8b2ce9b7c0 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfDataRequest.java @@ -0,0 +1,381 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import org.eclipse.linuxtools.tmf.Tracer; +import org.eclipse.linuxtools.tmf.event.TmfData; + +/** + * TmfDataRequest + *

+ * TmfDataRequests are used to obtain blocks of contiguous data from a data + * provider. Open ranges can be used, especially for continuous streaming. + *

+ * The request is processed asynchronously by a TmfProvider and, as blocks + * of data become available, handleData() is invoked synchronously for each + * block. Upon return, the data instances go out of scope and become eligible + * for gc. It is is thus the responsibility of the requester to either clone + * or keep a reference to the data it wishes to track specifically. + *

+ * This data block approach is used to avoid busting the heap for very + * large trace files. The block size is configurable. + *

+ * The TmfProvider indicates that the request is completed by calling done(). + * The request can be canceled at any time with cancel(). + *

+ * Typical usage: + *

TmfTimeWindow range = new TmfTimewindow(...);
+ *TmfDataRequest<DataType[]> request = new TmfDataRequest<DataType[]>(DataType.class, 0, NB_EVENTS, BLOCK_SIZE) {
+ *    public void handleData() {
+ *         DataType[] data = request.getData();
+ *         for (DataType e : data) {
+ *             // do something
+ *         }
+ *    }
+ *    public void handleSuccess() {
+ *         // do something
+ *         }
+ *    }
+ *    public void handleFailure() {
+ *         // do something
+ *         }
+ *    }
+ *    public void handleCancel() {
+ *         // do something
+ *         }
+ *    }
+ *};
+ *fProcessor.process(request, true);
+ *
+ * + * TODO: Consider decoupling from "time range", "rank", etc and for the more + * generic notion of "criteria". This would allow to extend for "time range", etc + * instead of providing specialized constructors. This also means removing the + * criteria info from the data structure (with the possible exception of fNbRequested). + * The nice thing about it is that it would prepare us well for the coming generation + * of analysis tools. + * + * TODO: Implement request failures (codes, etc...) + */ +public abstract class TmfDataRequest implements ITmfDataRequest { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + // The default maximum number of events per chunk + public static final int DEFAULT_BLOCK_SIZE = 1000; + + // The request count for all the events + public static final int ALL_DATA = Integer.MAX_VALUE; + + private static int fRequestNumber = 0; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final Class fDataType; + private final int fRequestId; // A unique request ID + private final int fIndex; // The index (rank) of the requested event + private final int fNbRequested; // The number of requested events (ALL_DATA for all) + private final int fBlockSize; // The maximum number of events per chunk + private int fNbRead; // The number of reads so far + + private final Object lock; + private boolean fRequestCompleted; + private boolean fRequestFailed; + private boolean fRequestCanceled; + + private T[] fData; // Data object + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Resets the request counter (used for testing) + */ + public static void reset() { + fRequestNumber = 0; + } + + /** + * Default constructor + * + * @param dataType the requested data type + */ + public TmfDataRequest(Class dataType) { + this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param dataType the requested data type + * @param nbRequested the number of data items requested + */ + public TmfDataRequest(Class dataType, int index) { + this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param dataType the requested data type + * @param index the index (rank) of the first event requested + * @param blockSize the number of data items per block + */ + public TmfDataRequest(Class dataType, int index, int nbRequested) { + this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE); + } + + /** + * @param dataType the requested data type + * @param index the index (rank) of the first event requested + * @param nbRequested the number of data items requested + * @param blockSize the number of data items per block + */ + public TmfDataRequest(Class dataType, int index, int nbRequested, int blockSize) { + fRequestId = fRequestNumber++; + fDataType = dataType; + fIndex = index; + fNbRequested = nbRequested; + fBlockSize = blockSize; + fNbRead = 0; + lock = new Object(); + + Tracer.trace("Request #" + fRequestId + " (" + getClass().getName() + ", " + fDataType.getName() + ") created"); + } + + /** + * Copy constructor + */ + @SuppressWarnings("unused") + private TmfDataRequest(TmfDataRequest other) { + fRequestId = 0; + fDataType = null; + fIndex = 0; + fNbRequested = 0; + fBlockSize = 0; + fNbRead = 0; + lock = new Object(); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the request ID + */ + public int getRequestId() { + return fRequestId; + } + + /** + * @return the index of the first event requested + */ + public int getIndex() { + return fIndex; + } + + /** + * @return the number of requested events (ALL_DATA = all) + */ + public int getNbRequested() { + return fNbRequested; + } + + /** + * @return the block size + */ + public int getBlockize() { + return fBlockSize; + } + + /** + * @return the number of events read so far + */ + public synchronized int getNbRead() { + return fNbRead; + } + + /** + * @return indicates if the request is completed + */ + public boolean isCompleted() { + return fRequestCompleted; + } + + /** + * @return indicates if the request is canceled + */ + public boolean isFailed() { + return fRequestFailed; + } + + /** + * @return indicates if the request is canceled + */ + public boolean isCancelled() { + return fRequestCanceled; + } + + /** + * @return the requested data type + */ + public Class getDataType() { + return fDataType; + } + + // ------------------------------------------------------------------------ + // Operators + // ------------------------------------------------------------------------ + + /** + * Sets the data object to specified value. To be called by the + * asynchronous method implementor. + * @param data Data value to set. + */ + public synchronized void setData(T[] data) { + fNbRead += data.length; + fData = data; + } + + /** + * Returns the data value, null if not set. + */ + public synchronized T[] getData() { + return fData; + } + + /** + * Handle a block of incoming data. This method is called every time + * a block of data becomes available. + * + * - Data items are received in the order they appear in the stream. + * - Called by the request processor, in its execution thread, every time a + * block of data becomes available. + * - Request processor performs a synchronous call to handlePartialResult() + * i.e. its execution threads holds until handlePartialData() returns. + * - Original data items are disposed of on return i.e. keep a reference + * (or a copy) if some persistence is needed between invocations. + * - When there is no more data, done() is called. + * + * @param events - an array of events + */ + public abstract void handleData(); + + /** + * Handle the completion of the request. It is called when there is no more + * data available either because: + * - the request completed normally + * - the request failed + * - the request was canceled + * + * As a convenience, handleXXXX methods are provided. They are meant to be + * overridden by the application if it needs to handle these conditions. + */ + public void handleCompleted() { + if (fRequestFailed) { + Tracer.trace("Request #" + fRequestId + " failed, completed"); + handleFailure(); + } + else if (fRequestCanceled) { + Tracer.trace("Request #" + fRequestId + " cancelled, completed"); + handleCancel(); + } + else { + Tracer.trace("Request #" + fRequestId + " succeeded, completed"); + handleSuccess(); + } + } + + public void handleSuccess() { + } + + public void handleFailure() { + } + + public void handleCancel() { + } + + /** + * To suspend the client thread until the request completes (or is + * canceled). + * + * @throws InterruptedException + */ + public void waitForCompletion() throws InterruptedException { + synchronized (lock) { + while (!fRequestCompleted) + lock.wait(); + } + } + + /** + * Called by the request processor upon completion. + */ + public void done() { + synchronized(lock) { + fRequestCompleted = true; + lock.notify(); + } + handleCompleted(); + } + + /** + * Called by the request processor upon failure. + */ + public void fail() { + synchronized(lock) { + fRequestFailed = true; + done(); + } + } + + /** + * Called by the request processor upon cancellation. + */ + public void cancel() { + synchronized(lock) { + fRequestCanceled = true; + done(); + } + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + // All requests have a unique id + public int hashCode() { + return getRequestId(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TmfDataRequest) { + TmfDataRequest request = (TmfDataRequest) other; + return (request.fDataType == fDataType) && + (request.fIndex == fIndex) && + (request.fNbRequested == fNbRequested); + } + return false; + } + + @Override + public String toString() { + return "[TmfDataRequest(" + fRequestId + "," + fDataType.getSimpleName() + + "," + fIndex + "," + fNbRequested + "," + fBlockSize + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfEventRequest.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfEventRequest.java new file mode 100644 index 0000000000..9a83500908 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfEventRequest.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * TmfEventRequest + *

+ * Implement me. Please. + */ +public abstract class TmfEventRequest extends TmfDataRequest implements ITmfEventRequest { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfTimeRange fRange; // The requested events time range + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param range + */ + public TmfEventRequest(Class dataType) { + this(dataType, TmfTimeRange.Eternity, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + */ + public TmfEventRequest(Class dataType, TmfTimeRange range) { + this(dataType, range, ALL_DATA, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + * @param nbRequested + */ + public TmfEventRequest(Class dataType, TmfTimeRange range, int nbRequested) { + this(dataType, range, nbRequested, DEFAULT_BLOCK_SIZE); + } + + /** + * @param range + * @param nbRequested + * @param blockSize Size of the largest blocks expected + */ + public TmfEventRequest(Class dataType, TmfTimeRange range, int nbRequested, int blockSize) { + super(dataType, 0, nbRequested, blockSize); + fRange = range; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the requested time range + */ + public TmfTimeRange getRange() { + return fRange; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + // All requests have a unique id + public int hashCode() { + return getRequestId(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TmfEventRequest) { + TmfEventRequest request = (TmfEventRequest) other; + return super.equals(other) && request.fRange.equals(fRange); + } + return false; + } + + @Override + public String toString() { + return "[TmfEventRequest(" + getRequestId() + "," + getDataType().getSimpleName() + + "," + getRange() + "," + getNbRequested() + "," + getBlockize() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfRequestExecutor.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfRequestExecutor.java new file mode 100644 index 0000000000..3b1d3d14b4 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/request/TmfRequestExecutor.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.request; + +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; + +import org.eclipse.linuxtools.tmf.Tracer; + +/** + * TmfRequestExecutor + * + * A simple, straightforward request executor. + */ +public class TmfRequestExecutor implements Executor { + + private final ExecutorService fExecutor; + private final String fExecutorName; + private final Queue fRequestQueue = new LinkedBlockingQueue(); + private Runnable fCurrentRequest; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public TmfRequestExecutor() { + this(Executors.newSingleThreadExecutor()); + } + + public TmfRequestExecutor(ExecutorService executor) { + fExecutor = executor; + String canonicalName = fExecutor.getClass().getCanonicalName(); + fExecutorName = canonicalName.substring(canonicalName.lastIndexOf('.') + 1); + Tracer.trace(fExecutor + " created"); + } + + /** + * @return the number of pending requests + */ + public int getNbPendingRequests() { + return fRequestQueue.size(); + } + + /** + * @return the shutdown state (i.e. if it is accepting new requests) + */ + public boolean isShutdown() { + return fExecutor.isShutdown(); + } + + /** + * @return the termination state + */ + public boolean isTerminated() { + return fExecutor.isTerminated(); + } + + /** + * Stops the executor + */ + public void stop() { + fExecutor.shutdown(); + Tracer.trace(fExecutor + " terminated"); + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see java.util.concurrent.Executor#execute(java.lang.Runnable) + */ + public synchronized void execute(final Runnable request) { + Tracer.trace("Queueing request " + request); + fRequestQueue.offer(new Runnable() { + public void run() { + try { + Tracer.trace("Processing request " + request); + request.run(); + Tracer.trace("Finishing request " + request); + } finally { + scheduleNext(); + } + } + }); + if (fCurrentRequest == null) { + scheduleNext(); + } + } + + /** + * Executes the next pending request, if applicable. + */ + protected synchronized void scheduleNext() { + if ((fCurrentRequest = fRequestQueue.poll()) != null) { + fExecutor.execute(fCurrentRequest); + } + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public String toString() { + return "[TmfRequestExecutor(" + fExecutorName + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfEndSynchSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfEndSynchSignal.java new file mode 100644 index 0000000000..caeaff17e7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfEndSynchSignal.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +/** + * TmfEndSynchSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfEndSynchSignal extends TmfSignal { + + public TmfEndSynchSignal(int synchId) { + super(null, synchId); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentSelectedSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentSelectedSignal.java new file mode 100644 index 0000000000..0bd452eff5 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentSelectedSignal.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; + +/** + * TmfExperimentSelectedSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfExperimentSelectedSignal extends TmfSignal { + + private final TmfExperiment fExperiment; + + public TmfExperimentSelectedSignal(Object source, TmfExperiment experiment) { + super(source); + fExperiment = experiment; + } + + public TmfExperiment getExperiment() { + return fExperiment; + } + + @Override + public String toString() { + return "[TmfExperimentSelectedSignal (" + fExperiment.getName() + ")]"; + } +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentUpdatedSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentUpdatedSignal.java new file mode 100644 index 0000000000..c8ede36950 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfExperimentUpdatedSignal.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; + +/** + * TmfExperimentUpdatedSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfExperimentUpdatedSignal extends TmfSignal { + + private final TmfExperiment fExperiment; + private final ITmfTrace fTrace; + + public TmfExperimentUpdatedSignal(Object source, TmfExperiment experiment, ITmfTrace trace) { + super(source); + fExperiment = experiment; + fTrace = trace; + } + + public TmfExperiment getExperiment() { + return fExperiment; + } + + public ITmfTrace getTrace() { + return fTrace; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TmfExperimentUpdatedSignal (" + fExperiment.toString() + ", " + fTrace.toString() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfRangeSynchSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfRangeSynchSignal.java new file mode 100644 index 0000000000..61f90eddad --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfRangeSynchSignal.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; + +/** + * TmfRangeSynchSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfRangeSynchSignal extends TmfSignal { + + private final TmfTimeRange fCurrentRange; + private final TmfTimestamp fCurrentTime; + + public TmfRangeSynchSignal(Object source, TmfTimeRange range, TmfTimestamp ts) { + super(source); + fCurrentRange = range; + fCurrentTime = ts; + } + + public TmfTimeRange getCurrentRange() { + return fCurrentRange; + } + + public TmfTimestamp getCurrentTime() { + return fCurrentTime; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignal.java new file mode 100644 index 0000000000..340bfc179e --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignal.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +/** + * TmfSignal + *

+ * TODO: Implement me. Please. + */ +public abstract class TmfSignal { + + // The signal originator + private final Object fSource; + + private int fReference; + + public TmfSignal(Object source) { + this(source, 0); + } + + public TmfSignal(Object source, int reference) { + fSource = source; + fReference = reference; + } + + public Object getSource() { + return fSource; + } + + public void setReference(int reference) { + fReference = reference; + } + + public int getReference() { + return fReference; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalHandler.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalHandler.java new file mode 100644 index 0000000000..238cea988c --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalHandler.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * TmfSignalHandler + *

+ * Marker for TMF signal handlers. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface TmfSignalHandler { + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalManager.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalManager.java new file mode 100644 index 0000000000..61f0b15be9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalManager.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * TmfSignalHandler + *

+ * This class manages the set of signal listeners and the signals they are + * interested in. When a signal is broadcasted, the appropriate listeners + * signal handlers are invoked. + *

+ */ +public class TmfSignalManager { + + // The set of event listeners and their corresponding handler methods. + // Note: listeners could be restricted to ITmfComponents but there is no + // harm in letting anyone use this since it is not tied to anything but + // the signal data type. + static private Map fListeners = new HashMap(); + + // If requested, add universal signal tracer + // TODO: Temporary solution: should be enabled/disabled dynamically + private static boolean fTraceIsActive = false; + private static TmfSignalTracer fSignalTracer; + static { + if (fTraceIsActive) { + fSignalTracer = TmfSignalTracer.getInstance(); + register(fSignalTracer); + } + } + + public static synchronized void register(Object listener) { + Method[] methods = getSignalHandlerMethods(listener); + if (methods.length > 0) + fListeners.put(listener, methods); + } + + public static synchronized void deregister(Object listener) { + fListeners.remove(listener); + } + + /** + * Returns the list of signal handlers in the listener. Signal handler name + * is irrelevant; only the annotation (@TmfSignalHandler) is important. + * + * @param listener + * @return + */ + static private Method[] getSignalHandlerMethods(Object listener) { + List handlers = new ArrayList(); + Method[] methods = listener.getClass().getMethods(); + for (Method method : methods) { + if (method.isAnnotationPresent(TmfSignalHandler.class)) { + handlers.add(method); + } + } + return handlers.toArray(new Method[handlers.size()]); + } + + /** + * Invokes the handling methods that listens to signals of a given type. + * + * The list of handlers is built on-the-fly to allow for the dynamic + * creation/deletion of signal handlers. Since the number of signal + * handlers shouldn't be too high, this is not a big performance issue + * to pay for the flexibility. + * + * For synchronization purposes, the signal is bracketed by two synch signals. + * + * @param signal the signal to dispatch + */ + static int fSynchId = 0; + static public synchronized void dispatchSignal(TmfSignal signal) { + fSynchId++; + sendSignal(new TmfStartSynchSignal(fSynchId)); + signal.setReference(fSynchId); + sendSignal(signal); + sendSignal(new TmfEndSynchSignal(fSynchId)); + } + + static private void sendSignal(TmfSignal signal) { + + // Build the list of listener methods that are registered for this signal + Class signalClass = signal.getClass(); + Map> listeners = new HashMap>(); + listeners.clear(); + for (Map.Entry entry : fListeners.entrySet()) { + List matchingMethods = new ArrayList(); + for (Method method : entry.getValue()) { + if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) { + matchingMethods.add(method); + } + } + if (!matchingMethods.isEmpty()) { + listeners.put(entry.getKey(), matchingMethods); + } + } + + // Call the signal handlers + for (Map.Entry> entry : listeners.entrySet()) { + for (Method method : entry.getValue()) { + try { + method.invoke(entry.getKey(), new Object[] { signal }); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + } + } + } + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalTracer.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalTracer.java new file mode 100644 index 0000000000..73ae15fa03 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfSignalTracer.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +/** + * TmfSignalTracer + *

+ * This object (singleton) traces all TmfSignals in the application. + */ +public class TmfSignalTracer { + + static TmfSignalTracer fInstance; + + static public TmfSignalTracer getInstance() { + if (fInstance == null) { + fInstance = new TmfSignalTracer(); + } + return fInstance; + } + + private TmfSignalTracer() { + } + + @TmfSignalHandler + public void traceSignal(TmfSignal signal) { + System.out.println(signal.getSource().toString() + ": " + signal.toString()); + } +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfStartSynchSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfStartSynchSignal.java new file mode 100644 index 0000000000..a833a16423 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfStartSynchSignal.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +/** + * TmfStartSynchSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfStartSynchSignal extends TmfSignal { + + + public TmfStartSynchSignal(int synchId) { + super(null, synchId); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTimeSynchSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTimeSynchSignal.java new file mode 100644 index 0000000000..861c0f3195 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTimeSynchSignal.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; + +/** + * TmfTimeSynchSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfTimeSynchSignal extends TmfSignal { + + private final TmfTimestamp fCurrentTime; + + public TmfTimeSynchSignal(Object source, TmfTimestamp ts) { + super(source); + fCurrentTime = ts; + } + + public TmfTimestamp getCurrentTime() { + return fCurrentTime; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TmfTimeSynchSignal (" + fCurrentTime.toString() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTraceUpdatedSignal.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTraceUpdatedSignal.java new file mode 100644 index 0000000000..ce48dc09b1 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/signal/TmfTraceUpdatedSignal.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.signal; + +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; + +/** + * TmfTraceUpdatedSignal + *

+ * TODO: Implement me. Please. + */ +public class TmfTraceUpdatedSignal extends TmfSignal { + + private final ITmfTrace fTrace; + private final TmfTimeRange fTimeRange; + + public TmfTraceUpdatedSignal(Object source, ITmfTrace trace, TmfTimeRange range) { + super(source); + fTrace = trace; + fTimeRange = range; + } + + public ITmfTrace getTrace() { + return fTrace; + } + + public TmfTimeRange getRange() { + return fTimeRange; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TmfTraceUpdatedSignal (" + fTrace.toString() + ", " + fTimeRange.toString() + ")]"; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfContext.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfContext.java new file mode 100644 index 0000000000..e0e9567fa8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfContext.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +/** + * ITmfContext + *

+ * This is a place-holder for the context objects. + */ +public interface ITmfContext { + + public long UNKNOWN_RANK = -1L; + + public void setLocation(ITmfLocation location); + public ITmfLocation getLocation(); + + public void setRank(long rank); + public long getRank(); + public void updateRank(int rank); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfLocation.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfLocation.java new file mode 100644 index 0000000000..20b20caf5e --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfLocation.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +/** + * ITmfLocation + *

+ * This is a place-holder for the location objects. + */ +public interface ITmfLocation extends Cloneable { + + public void setLocation(L location); + + public L getLocation(); + + public ITmfLocation clone(); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfTrace.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfTrace.java new file mode 100644 index 0000000000..0fcd9d0f94 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/ITmfTrace.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +import org.eclipse.linuxtools.tmf.component.ITmfComponent; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; + +/** + * ITmfTrace + *

+ */ +public interface ITmfTrace extends ITmfComponent { + + public ITmfTrace createTraceCopy(); + + + /** + * @return the trace path + */ + public String getPath(); + + /** + * @return the trace name + */ + public String getName(); + + /** + * @return the number of events in the trace + */ + public long getNbEvents(); + + /** + * Trace time range accessors + */ + public TmfTimeRange getTimeRange(); + public TmfTimestamp getStartTime(); + public TmfTimestamp getEndTime(); + + /** + * Positions the trace at the first event with the specified + * timestamp or index (i.e. the nth event in the trace). + * + * Returns a context which can later be used to read the event. + * + * @param data.timestamp + * @param data.index + * @return a context object for subsequent reads + */ + public TmfContext seekLocation(ITmfLocation location); + public TmfContext seekEvent(TmfTimestamp timestamp); + public TmfContext seekEvent(long rank); + + /** + * Return the event pointed by the supplied context (or null if + * no event left) and updates the context to the next event. + * + * @return the next event in the stream + */ + public TmfEvent getNextEvent(TmfContext context); + + /** + * Return the event pointed by the supplied context (or null if + * no event left) and *does not* update the context. + * + * @return the next event in the stream + */ + public TmfEvent parseEvent(TmfContext context); + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfCheckpoint.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfCheckpoint.java new file mode 100644 index 0000000000..6f19adf79c --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfCheckpoint.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; + +/** + * TmfCheckpoint + *

+ * This class maps an event timestamp to a generic location. + */ +public class TmfCheckpoint implements Comparable { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private final TmfTimestamp fTimestamp; + private final ITmfLocation fLocation; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + @SuppressWarnings("unused") + private TmfCheckpoint() { + fTimestamp = null; + fLocation = null; + } + + /** + * @param ts the checkpoint timestamp + * @param location the corresponding trace location + */ + public TmfCheckpoint(TmfTimestamp ts, ITmfLocation location) { + fTimestamp = ts; + fLocation = location; + } + + /** + * Deep copy constructor + * @param other the other checkpoint + */ + public TmfCheckpoint(TmfCheckpoint other) { + if (other == null) + throw new IllegalArgumentException(); + fTimestamp = (TmfTimestamp) other.fTimestamp.clone(); + fLocation = other.fLocation.clone(); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the checkpoint timestamp + */ + public TmfTimestamp getTimestamp() { + return fTimestamp; + } + + /** + * @return the checkpoint stream location + */ + public ITmfLocation getLocation() { + return fLocation; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + return fTimestamp.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfCheckpoint)) { + return false; + } + TmfCheckpoint o = (TmfCheckpoint) other; + return fTimestamp.equals(o.fTimestamp); + } + + @Override + public String toString() { + return "[TmfCheckpoint(" + fTimestamp + "," + fLocation + ")]"; + } + + // ------------------------------------------------------------------------ + // Comparable + // ------------------------------------------------------------------------ + + public int compareTo(TmfCheckpoint other) { + return fTimestamp.compareTo(other.fTimestamp, false); + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfContext.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfContext.java new file mode 100644 index 0000000000..89ca3239b9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfContext.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + + +/** + * TmfContext + *

+ * Trace context structure. It ties a trace location to an event rank. The + * context should be enough to restore the trace state so the corresponding + * event can be read. + */ +public class TmfContext implements ITmfContext, Cloneable { + + private ITmfLocation fLocation; + private long fRank; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public TmfContext(ITmfLocation loc, long rank) { + fLocation = loc; + fRank = rank; + } + + public TmfContext(ITmfLocation location) { + this(location, 0); + } + + public TmfContext(TmfContext other) { + this(other.fLocation, other.fRank); + } + + public TmfContext() { + this(null, 0); + } + + // ------------------------------------------------------------------------ + // ITmfContext + // ------------------------------------------------------------------------ + + public void setLocation(ITmfLocation location) { + fLocation = location; + } + + public ITmfLocation getLocation() { + return fLocation; + } + + public void setRank(long rank) { + fRank = rank; + } + + public long getRank() { + return fRank; + } + + public void updateRank(int delta) { + if (fRank != UNKNOWN_RANK) + fRank += delta; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + fLocation.hashCode(); + result = 37 * result + (int) (fRank ^ (fRank >>> 32)); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfContext)) { + return false; + } + TmfContext o = (TmfContext) other; + return fLocation.equals(o.fLocation) && (fRank == o.fRank); + } + + @Override + public String toString() { + return "[TmfContext(" + fLocation.toString() + "," + fRank + ")]"; + } + + @Override + public TmfContext clone() { + TmfContext clone = null; + try { + clone = (TmfContext) super.clone(); + clone.fLocation = fLocation.clone(); + clone.fRank = fRank; + } catch (CloneNotSupportedException e) { + } + return clone; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfLocation.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfLocation.java new file mode 100644 index 0000000000..40d736456f --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfLocation.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +import java.lang.reflect.Method; + +/** + * TmfLocation + *

+ * A generic implementation of ITmfLocation + */ +public class TmfLocation implements ITmfLocation { + + private L fLocation; + + @SuppressWarnings("unused") + private TmfLocation() { + } + + public TmfLocation(L location) { + fLocation = location; + } + + public TmfLocation(TmfLocation other) { + if (other == null) + throw new IllegalArgumentException(); + fLocation = other.fLocation; + } + + public void setLocation(L location) { + fLocation = location; + } + + public L getLocation() { + return fLocation; + } + + // ------------------------------------------------------------------------ + // Object + // ------------------------------------------------------------------------ + + @Override + public int hashCode() { + return fLocation.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TmfLocation)) + return false; + TmfLocation o = (TmfLocation) other; + return fLocation.equals(o.fLocation); + } + + @Override + public String toString() { + return fLocation.toString(); + } + + @SuppressWarnings("unchecked") + @Override + public TmfLocation clone() { + TmfLocation clone = null; + try { + clone = (TmfLocation) super.clone(); + Class clazz = this.fLocation.getClass(); + Method method = clazz.getMethod("clone", new Class[0]); + Object duplic = method.invoke(this.fLocation, new Object[0]); + clone.fLocation = (L) duplic; + } catch (NoSuchMethodException e) { + // exception suppressed + } catch (Exception e) { + throw new InternalError(e.toString()); + } + return clone; + } + +} diff --git a/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfTrace.java b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfTrace.java new file mode 100644 index 0000000000..06b9716c80 --- /dev/null +++ b/org.eclipse.linuxtools.tmf/src/org/eclipse/linuxtools/tmf/trace/TmfTrace.java @@ -0,0 +1,467 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.trace; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Collections; +import java.util.Vector; + +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.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.signal.TmfTraceUpdatedSignal; + +/** + * TmfTrace + *

+ * Abstract implementation of ITmfTrace. It should be sufficient to extend this + * class and provide implementation for getCurrentLocation() and + * seekLocation(), as well as a proper parser, to have a working + * concrete implementation. + *

+ * Note: The notion of event rank is still under heavy discussion. Although + * used by the Events View and probably useful in the general case, there + * is no easy way to implement it for LTTng (actually a strong case is being + * made that this is useless). + *

+ * That it is not supported by LTTng does by no mean indicate that it is not + * useful for (just about) every other tracing tool. Therefore, this class + * provides a minimal (and partial) implementation of rank. However, the current + * implementation should not be relied on in the general case. + * + * TODO: Add support for live streaming (notifications, incremental indexing, ...) + */ +public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, Cloneable { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + + // The default number of events to cache + // TODO: Make the DEFAULT_CACHE_SIZE a preference + public static final int DEFAULT_CACHE_SIZE = 1000; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + // The trace path + private final String fPath; + + // The cache page size AND checkpoints interval + protected int fIndexPageSize; + + // The set of event stream checkpoints (for random access) + protected Vector fCheckpoints = new Vector(); + + // The number of events collected + protected long fNbEvents = 0; + + // The time span of the event stream + private TmfTimeRange fTimeRange = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigBang); + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * @param path + * @throws FileNotFoundException + */ + protected TmfTrace(String name, Class type, String path) throws FileNotFoundException { + this(name, type, path, DEFAULT_CACHE_SIZE); + } + + /** + * @param path + * @param cacheSize + * @throws FileNotFoundException + */ + protected TmfTrace(String name, Class type, String path, int cacheSize) throws FileNotFoundException { + super(name, type); + int sep = path.lastIndexOf(File.separator); + String simpleName = (sep >= 0) ? path.substring(sep + 1) : path; + setName(simpleName); + fPath = path; + fIndexPageSize = (cacheSize > 0) ? cacheSize : DEFAULT_CACHE_SIZE; + } + + /* (non-Javadoc) + * @see java.lang.Object#clone() + */ + @SuppressWarnings("unchecked") + @Override + public TmfTrace clone() throws CloneNotSupportedException { + TmfTrace clone = (TmfTrace) super.clone(); + clone.fCheckpoints = (Vector) fCheckpoints.clone(); + clone.fTimeRange = new TmfTimeRange(fTimeRange); + return clone; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return the trace path + */ + public String getPath() { + return fPath; + } + +// /** +// * @return the trace name +// */ +// @Override +// public String getName() { +// return fName; +// } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents() + */ + public long getNbEvents() { + return fNbEvents; + } + + /** + * @return the size of the cache + */ + public int getCacheSize() { + return fIndexPageSize; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange() + */ + public TmfTimeRange getTimeRange() { + return fTimeRange; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime() + */ + public TmfTimestamp getStartTime() { + return fTimeRange.getStartTime(); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime() + */ + public TmfTimestamp getEndTime() { + return fTimeRange.getEndTime(); + } + + @SuppressWarnings("unchecked") + public Vector getCheckpoints() { + return (Vector) fCheckpoints.clone(); + } + + // ------------------------------------------------------------------------ + // Operators + // ------------------------------------------------------------------------ + + protected void setTimeRange(TmfTimeRange range) { + fTimeRange = range; + } + + protected void setStartTime(TmfTimestamp startTime) { + fTimeRange = new TmfTimeRange(startTime, fTimeRange.getEndTime()); + } + + protected void setEndTime(TmfTimestamp endTime) { + fTimeRange = new TmfTimeRange(fTimeRange.getStartTime(), endTime); + } + + // ------------------------------------------------------------------------ + // TmfProvider + // ------------------------------------------------------------------------ + + @Override + public ITmfContext armRequest(ITmfDataRequest request) { + if (request instanceof ITmfEventRequest) { + return seekEvent(((ITmfEventRequest) request).getRange().getStartTime()); + } + return seekEvent(request.getIndex()); + } + + /** + * Return the next piece of data based on the context supplied. The context + * would typically be updated for the subsequent read. + * + * @param context + * @return + */ + @SuppressWarnings("unchecked") + @Override + public T getNext(ITmfContext context) { + if (context instanceof TmfContext) { + return (T) getNextEvent((TmfContext) context); + } + return null; + } + + // ------------------------------------------------------------------------ + // ITmfTrace + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp) + */ + public TmfContext seekEvent(TmfTimestamp timestamp) { + + 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 stream 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; + } + } + TmfContext context = seekLocation(location); + context.setRank(index * fIndexPageSize); + + // And locate the event + TmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype... + TmfEvent event = getNextEvent(nextEventContext); + while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { + context.setLocation(nextEventContext.getLocation().clone()); + context.updateRank(1); + event = getNextEvent(nextEventContext); + } + + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int) + */ + public TmfContext seekEvent(long rank) { + + // 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(); + } + } + + TmfContext context = seekLocation(location); + long pos = index * fIndexPageSize; + context.setRank(pos); + + if (pos < rank) { + TmfEvent event = getNextEvent(context); + while (event != null && ++pos < rank) { + event = getNextEvent(context); + } + } + + return context; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext) + */ + public synchronized TmfEvent getNextEvent(TmfContext context) { + // parseEvent() does not update the context + TmfEvent event = parseEvent(context); + if (event != null) { + context.setLocation(getCurrentLocation()); + context.updateRank(1); + processEvent(event); + } + return event; + } + + /** + * Hook for "special" processing by the concrete class + * (called by getNextEvent()) + * + * @param event + */ + protected void processEvent(TmfEvent event) { + // Do nothing by default + } + + /** + * To be implemented by the concrete class + */ + public abstract TmfContext seekLocation(ITmfLocation location); + public abstract ITmfLocation getCurrentLocation(); + public abstract TmfEvent parseEvent(TmfContext context); + + // ------------------------------------------------------------------------ + // toString + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TmfTrace (" + getName() + ")]"; + } + + // ------------------------------------------------------------------------ + // Indexing + // ------------------------------------------------------------------------ + + /* + * The purpose of the index is to perform a pass over the trace and collect + * basic information that can be later used to rapidly access a trace events. + * + * The information collected: + * - fCheckpoints, the list of evenly separated checkpoints (timestamp + location) + * - fTimeRange, the trace time span + * - fNbEvents, the number of events in the trace + * + * NOTE: Doesn't work for streaming traces. + */ + + private IndexingJob job; + + // Indicates that an indexing job is already running + private boolean fIndexing = false; + private Boolean fIndexed = false; + + public void indexTrace(boolean waitForCompletion) { + synchronized (this) { + if (fIndexed || fIndexing) { + return; + } + fIndexing = true; + } + + job = new IndexingJob("Indexing " + getName()); + 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) { + + monitor.beginTask("Indexing " + getName(), IProgressMonitor.UNKNOWN); + + int nbEvents = 0; + TmfTimestamp startTime = null; + TmfTimestamp lastTime = null; + + // Reset the index + fCheckpoints = new Vector(); + + try { + // Position the trace at the beginning + TmfContext context = seekLocation(null); + ITmfLocation location = context.getLocation().clone(); + + // Get the first event + TmfEvent event = getNextEvent(context); + if (event != null) { + startTime = new TmfTimestamp(event.getTimestamp()); + } + + // Index the trace + while (event != null) { + lastTime = event.getTimestamp(); + if ((nbEvents++ % fIndexPageSize) == 0) { + lastTime = new TmfTimestamp(event.getTimestamp()); + fCheckpoints.add(new TmfCheckpoint(lastTime, location)); + + monitor.worked(1); + + // Check monitor *after* fCheckpoints has been updated + if (monitor.isCanceled()) { + monitor.done(); + return Status.CANCEL_STATUS; + } + } + + // We will need this location at the next iteration + if ((nbEvents % fIndexPageSize) == 0) { + location = context.getLocation().clone(); + } + + event = getNextEvent(context); + } + } + finally { + synchronized(this) { + fNbEvents = nbEvents; + fTimeRange = new TmfTimeRange(startTime, lastTime); + fIndexing = false; + fIndexed = true; + } + notifyListeners(fTimeRange); + monitor.done(); + } + + return Status.OK_STATUS; + } + } + + protected void notifyListeners(TmfTimeRange range) { + broadcast(new TmfTraceUpdatedSignal(this, this, range)); + } + +} -- 2.34.1