dev guide: add section for TMF remote API
[deliverable/tracecompass.git] / doc / org.eclipse.tracecompass.doc.dev / doc / Developer-Guide.mediawiki
index 7be5d07f2f531374f3d034f96b2dfaac9f03d317..7784d1e4c70035f0f3c980d5a11d84857e4a2422 100644 (file)
@@ -21,7 +21,7 @@ The framework can easily be extended to support more trace types. To make a new
 trace type, one must define the following items:
 
 * The event type
-* The trace reader
+* The trace type
 * The trace context
 * The trace location
 * The ''org.eclipse.linuxtools.tmf.core.tracetype'' plug-in extension point
@@ -31,9 +31,10 @@ The '''event type''' must implement an ''ITmfEvent'' or extend a class that
 implements an ''ITmfEvent''. Typically it will extend ''TmfEvent''. The event
 type must contain all the data of an event.
 
-The '''trace reader''' must be of an ''ITmfTrace'' type. The ''TmfTrace'' class
+The '''trace type''' must be of an ''ITmfTrace'' type. The ''TmfTrace'' class
 will supply many background operations so that the reader only needs to
-implement certain functions.
+implement certain functions. This includes the ''event aspects'' for events of
+this trace type. See the section below.
 
 The '''trace context''' can be seen as the internals of an iterator. It is
 required by the trace reader to parse events as it iterates the trace and to
@@ -46,6 +47,57 @@ therefore, it needs to contain enough information to unambiguously point to one
 and only one event. Finally the ''tracetype'' plug-in extension associates a
 given trace, non-programmatically to a trace type for use in the UI.
 
+== Event Aspects ==
+
+In Trace Compass, an ''event aspect'' represents any type of information that
+can be extracted from a trace event. The simple case is information that is
+present directly in the event. For example, the timestamp of an event, a field
+of an LTTng event, or the "payload" that is on the same line of a text trace
+entry. But it could also be the result of an indirect operation, for example a
+state system query at the timestamp of the given event (see the section
+[[#Generic State System]]).
+
+All aspects should implement the '''ITmfEventAspect''' interface. The important
+method in there is ''resolve(ITmfEvent)'', which tells this aspect what to
+output for a given event. The singleton pattern fits well for pre-defined aspect
+classes, in general.
+
+The aspects defined for a trace type determine the initial columns in the Event
+Table, as well as the elements on which the trace can be filtered, among other
+things.
+
+=== Base and custom aspects ===
+
+Some base aspects are defined in '''TmfTrace#BASE_ASPECTS'''. They use generic
+methods found in '''ITmfEvent''', so they should be applicable for any event
+type defined in the framework. If one does not override
+'''TmfTrace#getEventAspects''', then only the base aspects will be used with
+this trace.
+
+Overriding the method does not append to this list, it replaces it. So if you
+wish to define additional aspects for a new trace type, do not forget to include
+the BASE_ASPECTS you want to use, if any, within the list.
+
+The order of the elements in the returned ''Iterable'' may matter to other
+components. For instance, the initial ordering of the columns in the Events
+Table will match it.
+
+Defining additional aspects allows to expose more data from the trace events
+without having to update all the views using the aspects API.
+
+=== Creating event aspects programmatically ===
+
+Another advantage of event aspects is that they can be created programmatically,
+without having to modify the base trace or event classes. A new analysis
+applying to a pre-existing trace type may wish to define additional aspects to
+make its job easier.
+
+While the notion of event aspects should not be exposed to users directly, it is
+possible to create new aspects based on user input. For example, an "event
+field" dialog could ask the user to enter a field name, which would then create
+an aspect that would look for the value of a field with this name in every
+event. The user could then be able to display or filter on this aspect.
+
 == Optional Trace Type Attributes ==
 
 After defining the trace type as described in the previous chapters it is
@@ -809,7 +861,7 @@ Sent by TmfCheckpointIndexer when new events have been indexed and the number of
 
 Received by components that need to be notified of a new trace event count.
 
-=== TmfTimeSynchSignal ===
+=== TmfSelectionRangeUpdatedSignal ===
 
 ''Purpose''
 
@@ -825,7 +877,7 @@ Sent by any component that allows the user to select a time or time range.
 
 Received by any component that needs to be notified of the currently selected time or time range.
 
-=== TmfRangeSynchSignal ===
+=== TmfWindowRangeUpdatedSignal ===
 
 ''Purpose''
 
@@ -3367,6 +3419,164 @@ Here's a list of features not yet implemented that would improve the analysis mo
 * Add the possibility for an analysis requirement to be composed of another requirement.
 * Generate a trace session from analysis requirements.
 
+= TMF Remote API =
+The TMF remote API is based on the remote services implementation of the Eclipse PTP project. It comes with a built-in SSH implementation based JSch as well as with support for a local connection. The purpose of this API is to provide a programming interface to the PTP remote services implementation for connection handling, command-line execution and file transfer handling. It provides utility functions to simplify repetitive tasks.
+
+The TMF Remote API can be used for remote trace control, fetching of traces from a remote host into the Eclipse Tracing project or uploading files to the remote host. For example, the LTTng tracer control feature uses the TMF remote API to control an LTTng host remotely and to download corresponding traces.
+
+In the following chapters the relevant classes and features of the TMF remote API is described.
+
+== Prerequisites ==
+
+To use the TMF remote API one has to add the relevant plug-in dependencies to a plug-in project. To create a plug-in project see chapter [[#Creating an Eclipse UI Plug-in]].
+
+To add plug-in dependencies double-click on the MANIFEST.MF file. Change to the Dependencies tab and select '''Add...''' of the ''Required Plug-ins'' section. A new dialog box will open. Next find plug-in ''org.eclipse.tracecompass.tmf.remote.core'' and press '''OK'''. Follow the same steps, add ''org.eclipse.remote.core''. If UI elements are needed in the plug-in also add ''org.eclipse.tracecompass.tmf.remote.ui'' and ''org.eclipse.remote.ui''.
+
+== TmfRemoteConnectionFactory ==
+This class is a utility class for creating ''IRemoteConnection'' instances of PTP programatically. It also provides access methods to the OSGI remote services of PTP.
+
+=== Accessing the remote services manager (OSGI service) ===
+The main entry point into the PTP remote services system is the ''IRemoteServicesManager'' OSGI service. It provides a list of connection types and the global list of all connections.
+
+To access an OSGI service, use the method '''getService()''' of the '''TmfRemoteConnectionFactory''' class:
+
+<pre>
+IRemoteServicesManager manager = TmfRemoteConnectionFactory.getService(IRemoteServicesManager.class);
+</pre>
+
+=== Obtaining a IRemoteConnection ===
+To obtain an '''IRemoteConnection''' instance use the method '''TmfRemoteConnectionFactory.getRemoteConnection(String remoteServicesId, String name)''', where ''remoteServicesId'' is the ID of service ID for the connection, and ''name'' the name of the connection. For built-in SSH the ''remoteServicesId'' is "org.eclipse.remote.JSch".
+
+<pre>
+IRemoteConnection connection = TmfRemoteConnectionFactory.getRemoteConnection("org.eclipse.remote.JSch", "My Connection");
+</pre>
+
+Note that the connection needs to be created beforehand using the Remote Connection wizard implementation ('''Window -> Preferences -> Remote Development -> Remote Connection''') in the Eclipse application that executes this plug-in. For more information about creating connections using the Remote Connections feature of PTP refer to [http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.ptp.doc.user%2Fhtml%2FremoteTools.html&anchor=remote link]. Alternatively it can be created programmatically using the corresponding API of TMF ([[#Creating an IRemoteConnection instance]]).
+
+To obtain an '''IRemoteConnection''' instance use method '''TmfRemoteConnectionFactory.getLocalConnection()'''.
+<pre>
+IRemoteConnection connection = TmfRemoteConnectionFactory.getLocalConnection();
+</pre>
+
+=== Creating an IRemoteConnection instance ===
+It is possible to create an '''IRemoteConnection''' instance programmatically using the '''TmfRemoteConnectionFactory'''. Right now only build-in SSH or Local connection is supported.
+
+To create an '''IRemoteConnection''' instance use the method '''createConnection(URI hostURI, String name)''' of class '''TmfRemoteConnectionFactory''', where ''hostURI'' is the URI of the remote connection, and ''name'' the name of the connection. For a built-in SSH use:
+<pre>
+import org.eclipse.remote.core.IRemoteConnection;
+...
+    try {
+        URI hostUri = URIUtil.fromString("ssh://userID@127.0.0.1:22");
+        IRemoteConnection connection = TmfRemoteConnectionFactory.createConnection(hostUri, "MyHost");
+    } catch (URISyntaxException e) {
+        return new Status(IStatus.ERROR, "my.plugin.id", "URI syntax error", e);
+    } catch (RemoteConnectionException e) {
+        return new Status(IStatus.ERROR, "my.plugin.id", "Connection cannot be created", e);
+    }
+...
+</pre>
+
+Note that if a connection already exists with the given name then this connection will be returned.
+
+=== Providing a connection factory ===
+Right now only build-in SSH or Local connection of PTP is supported. If one wants to provide another connection factory with a different remote service implementation use the interface '''IConnectionFactory''' to implement a new connection factory class. Then, register the new factory to '''TmfRemoteConnectionFactory''' using method '''registerConnectionFactory(String connectionTypeId, IConnectionFactory factory)''', where ''connectionTypeId'' is a unique ID and ''factory'' is the corresponding connection factory implementation.
+
+== RemoteSystemProxy ==
+The purpose of the RemoteSystemProxy is to handle the connection state of '''IRemoteConnection''' (connect/disconnect). Before opening a connection it checks if the connection had been open previously. If it was open, disconnecting the proxy will not close the connection. This is useful if multiple components using the same connection at the same time for different features (e.g. Tracer Control and remote fetching of traces) without impacting each other.
+
+=== Creating a RemoteSystemProxy ===
+Once one has an '''IRemoteConnection''' instance a '''RemoteSystemProxy''' can be constructed by:
+<pre>
+// Get local connection (for example)
+IRemoteConnection connection = TmfRemoteConnectionFactory.getLocalConnection();
+RemoteSystemProxy proxy = new RemoteSystemProxy(connection);
+</pre>
+
+=== Opening the remote connection ===
+To open the connection call method '''connect()''':
+<pre>
+    proxy.connect();
+</pre>
+
+This will open the connection. If the connection has been previously opened then it will immediately return.
+
+=== Closing the remote connection ===
+To close the connection call method '''disconnect()''':
+<pre>
+    proxy.disconnect();
+</pre>
+
+Note: This will close the connection if the connection was opened by this proxy. Otherwise it will stay open.
+
+=== Disposing the remote connection ===
+If a remote system proxy is not needed anymore the proxy instance needs to be disposed by calling method '''dispose()'''. This may close the connection if the connection was opened by this proxy. Otherwise it will stay open.
+
+<pre>
+    proxy.dispose();
+</pre>
+
+=== Checking the connection state ===
+
+To check the connection state use method '''isConnected()''' of the '''RemoteSystemProxy''' class.
+
+<pre>
+    if (proxy.isConnected()) {
+        // do something
+    }
+</pre>
+
+
+=== Retrieving the IRemoteConnection instance ===
+To retrieve the '''IRemoteConnection''' instance use the '''getRemoteConnection()''' method of the '''RemoteSystemProxy''' class. Using this instance relevant features of the remote connection implementation can be accessed, for example remote file service ('''IRemoteFileService''') or remote process service ('''IRemoteProcessService''').
+
+<pre>
+import org.eclipse.remote.core.IRemoteConnection;
+import org.eclipse.remote.core.IRemoteFileService;
+...
+    IRemoteRemoteConnection connection = proxy.getRemoteConnection();
+    IRemoteFileService fileService = connection.getService(IRemoteFileService.class);
+    if (fileService != null) {
+        // do something (e.g. download or upload a file)
+    }
+</pre>
+
+<pre>
+import org.eclipse.remote.core.IRemoteConnection;
+import org.eclipse.remote.core.IRemoteFileService;
+...
+    IRemoteRemoteConnection connection = proxy.getRemoteConnection();
+    IRemoteFileService processService = connection.getService(IRemoteProcessService.class);
+    if (processService != null) {
+        // do something (e.g. execute command)
+    }
+</pre>
+
+=== Obtaining a command shell ===
+The TMF remote API provides a Command shell implementation to execute remote command-line commands. To obtain a command-line shell use the RemoteSystemProxy. 
+
+<pre>
+import org.eclipse.remote.core.IRemoteConnection;
+import org.eclipse.remote.core.IRemoteFileService;
+import org.eclipse.tracecompass.tmf.remote.core.shell.ICommandShell
+...
+    ICommandShell shell = proxy.createCommandShell();
+    ICommandInput command = fCommandShell.createCommand();
+    command.add("ls");
+    command.add("-l");
+    ICommandResult result = shell.executeCommand(command, new NullProgressMonitor);
+    System.out.println("Return value: " result.getResult());
+    for (String line : result.getOutput()) {
+        System.out.println(line);
+    }
+    for (String line : result.getErrorOutput()) {
+        System.err.println(line);
+    }
+    shell.dispose();
+</pre>
+
+Note that the shell needs to be disposed if not needed anymore.
+
+Note for creating a command with parameters using the '''CommandInput''' class, add the command and each parameter separately instead of using one single String.
 
 = Performance Tests =
 
@@ -3416,7 +3626,7 @@ public class AnalysisBenchmark {
         for (int i = 0; i < LOOP_COUNT; i++) {
 
             /** Start each run of the test with new objects to avoid different code paths */
-            try (IAnalysisModule module = new LttngKernelAnalysisModule();
+            try (IAnalysisModule module = new KernelAnalysis();
                     LttngKernelTrace trace = new LttngKernelTrace()) {
                 module.setId("test");
                 trace.initTrace(null, testTrace.getPath(), CtfTmfEvent.class);
This page took 0.029878 seconds and 5 git commands to generate.