4 The purpose of the '''Tracing Monitoring Framework (TMF)''' is to facilitate the integration of tracing and monitoring tools into Eclipse, to provide out-of-the-box generic functionalities/views and provide extension mechanisms of the base functionalities for application specific purposes.
6 = Component Interaction =
8 TMF provides a mechanism for different components to interact with each other using signals. The signals can carry information that is specific to each signal.
10 The TMF Signal Manager handles registration of components and the broadcasting of signals to their intended receivers.
12 Components can register as VIP receivers which will ensure they will receive the signal before non-VIP receivers.
16 In order to send a signal, an instance of the signal must be created and passed as argument to the signal manager to be dispatched. Every component that can handle the signal will receive it. The receivers do not need to be known by the sender.
19 TmfExampleSignal signal = new TmfExampleSignal(this, ...);
20 TmfSignalManager.dispatchSignal(signal);
23 If the sender is an instance of the class TmfComponent, the broadcast method can be used:
26 TmfExampleSignal signal = new TmfExampleSignal(this, ...);
30 == Receiving Signals ==
32 In order to receive any signal, the receiver must first be registered with the signal manager. The receiver can register as a normal or VIP receiver.
35 TmfSignalManager.register(this);
36 TmfSignalManager.registerVIP(this);
39 If the receiver is an instance of the class TmfComponent, it is automatically registered as a normal receiver in the constructor.
41 When the receiver is destroyed or disposed, it should deregister itself from the signal manager.
44 TmfSignalManager.deregister(this);
47 To actually receive and handle any specific signal, the receiver must use the @TmfSignalHandler annotation and implement a method that will be called when the signal is broadcast. The name of the method is irrelevant.
51 public void example(TmfExampleSignal signal) {
56 The source of the signal can be used, if necessary, by a component to filter out and ignore a signal that was broadcast by itself when the component is also a receiver of the signal but only needs to handle it when it was sent by another component or another instance of the component.
58 == Signal Throttling ==
60 It is possible for a TmfComponent instance to buffer the dispatching of signals so that only the last signal queued after a specified delay without any other signal queued is sent to the receivers. All signals that are preempted by a newer signal within the delay are discarded.
62 The signal throttler must first be initialized:
65 final int delay = 100; // in ms
66 TmfSignalThrottler throttler = new TmfSignalThrottler(this, delay);
69 Then the sending of signals should be queued through the throttler:
72 TmfExampleSignal signal = new TmfExampleSignal(this, ...);
73 throttler.queue(signal);
76 When the throttler is no longer needed, it should be disposed:
82 == Signal Reference ==
84 The following is a list of built-in signals defined in the framework.
86 === TmfStartSynchSignal ===
90 This signal is used to indicate the start of broadcasting of a signal. Internally, the data provider will not fire event requests until the corresponding TmfEndSynchSignal signal is received. This allows coalescing of requests triggered by multiple receivers of the broadcast signal.
94 Sent by TmfSignalManager before dispatching a signal to all receivers.
98 Received by TmfDataProvider.
100 === TmfEndSynchSignal ===
104 This signal is used to indicate the end of broadcasting of a signal. Internally, the data provider fire all pending event requests that were received and buffered since the corresponding TmfStartSynchSignal signal was received. This allows coalescing of requests triggered by multiple receivers of the broadcast signal.
108 Sent by TmfSignalManager after dispatching a signal to all receivers.
112 Received by TmfDataProvider.
114 === TmfTraceOpenedSignal ===
118 This signal is used to indicate that a trace has been opened in an editor.
122 Sent by a TmfEventsEditor instance when it is created.
126 Received by TmfTrace, TmfExperiment, TmfTraceManager and every view that shows trace data. Components that show trace data should handle this signal.
128 === TmfTraceSelectedSignal ===
132 This signal is used to indicate that a trace has become the currently selected trace.
136 Sent by a TmfEventsEditor instance when it receives focus. Components can send this signal to make a trace editor be brought to front.
140 Received by TmfTraceManager and every view that shows trace data. Components that show trace data should handle this signal.
142 === TmfTraceClosedSignal ===
146 This signal is used to indicate that a trace editor has been closed.
150 Sent by a TmfEventsEditor instance when it is disposed.
154 Received by TmfTraceManager and every view that shows trace data. Components that show trace data should handle this signal.
156 === TmfTraceRangeUpdatedSignal ===
160 This signal is used to indicate that the valid time range of a trace has been updated. This triggers indexing of the trace up to the end of the range. In the context of streaming, this end time is considered a safe time up to which all events are guaranteed to have been completely received. For non-streaming traces, the end time is set to infinity indicating that all events can be read immediately. Any processing of trace events that wants to take advantage of request coalescing should be triggered by this signal.
164 Sent by TmfExperiment and non-streaming TmfTrace. Streaming traces should send this signal in the TmfTrace subclass when a new safe time is determined by a specific implementation.
168 Received by TmfTrace, TmfExperiment and components that process trace events. Components that need to process trace events should handle this signal.
170 === TmfTraceUpdatedSignal ===
174 This signal is used to indicate that new events have been indexed for a trace.
178 Sent by TmfCheckpointIndexer when new events have been indexed and the number of events has changed.
182 Received by components that need to be notified of a new trace event count.
184 === TmfTimeSynchSignal ===
188 This signal is used to indicate that a new time has been selected.
192 Sent by any component that allows the user to select a time.
196 Received by any component that needs to be notified of the currently selected time.
198 === TmfRangeSynchSignal ===
202 This signal is used to indicate that a new time range window has been set.
206 Sent by any component that allows the user to set a time range window.
210 Received by any component that needs to be notified of the current visible time range window.
212 === TmfEventFilterAppliedSignal ===
216 This signal is used to indicate that a filter has been applied to a trace.
220 Sent by TmfEventsTable when a filter is applied.
224 Received by any component that shows trace data and needs to be notified of applied filters.
226 === TmfEventSearchAppliedSignal ===
230 This signal is used to indicate that a search has been applied to a trace.
234 Sent by TmfEventsTable when a search is applied.
238 Received by any component that shows trace data and needs to be notified of applied searches.
240 === TmfTimestampFormatUpdateSignal ===
244 This signal is used to indicate that the timestamp format preference has been updated.
248 Sent by TmfTimestampFormat when the default timestamp format preference is changed.
252 Received by any component that needs to refresh its display for the new timestamp format.
254 === TmfStatsUpdatedSignal ===
258 This signal is used to indicate that the statistics data model has been updated.
262 Sent by statistic providers when new statistics data has been processed.
266 Received by statistics viewers and any component that needs to be notified of a statistics update.
270 TMF has built-in Eclipse tracing support for the debugging of signal interaction between components. To enable it, open the '''Run/Debug Configuration...''' dialog, select a configuration, click the '''Tracing''' tab, select the plug-in '''org.eclipse.linuxtools.tmf.core''', and check the '''signal''' item.
272 All signals sent and received will be logged to the file TmfTrace.log located in the Eclipse home directory.
274 = TMF UML2 Sequence Diagram Framework =
276 The purpose of the UML2 Sequence Diagram Framework of TMF is to provide a framework for generation of UML2 sequence diagrams. It provides
277 *UML2 Sequence diagram drawing capabilities (i.e. lifelines, messages, activations, object creation and deletion)
278 *a generic, re-usable Sequence Diagram View
279 *Eclipse Extension Point for the creation of sequence diagrams
280 *callback hooks for searching and filtering within the Sequence Diagram View
282 The following chapters describe the Sequence Diagram Framework as well as a reference implementation and its usage.
284 == TMF UML2 Sequence Diagram Extensions ==
286 In the UML2 Sequence Diagram Framework an Eclipse extension point is defined so that other plug-ins can contribute code to create sequence diagram.
288 '''Identifier''': org.eclipse.linuxtools.tmf.ui.uml2SDLoader<br>
289 '''Since''': Since 0.3.2 (based on UML2SD of org.eclipse.tptp.common.ui)<br>
290 '''Description''': This extension point aims to list and connect any UML2 Sequence Diagram loader.<br>
291 '''Configuration Markup''':<br>
294 <!ELEMENT extension (uml2SDLoader)+>
296 point CDATA #REQUIRED
302 *point - A fully qualified identifier of the target extension point.
303 *id - An optional identifier of the extension instance.
304 *name - An optional name of the extension instance.
307 <!ELEMENT uml2SDLoader EMPTY>
308 <!ATTLIST uml2SDLoader
311 class CDATA #REQUIRED
313 default (true | false)
316 *id - A unique identifier for this uml2SDLoader. This is not mandatory as long as the id attribute cannot be retrieved by the provider plug-in. The class attribute is the one on which the underlying algorithm relies.
317 *name - An name of the extension instance.
318 *class - The implementation of this UML2 SD viewer loader. The class must implement org.eclipse.linuxtools.tmf.ui.views.uml2sd.load.IUml2SDLoader.
319 *view - The view ID of the view that this loader aims to populate. Either org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView itself or a extension of org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView.
320 *default - Set to true to make this loader the default one for the view; in case of several default loaders, first one coming from extensions list is taken.
323 == Management of the Extension Point ==
325 The TMF UI plug-in is responsible for evaluating each contribution to the extension point.
328 With this extension point, a loader class is associated with a Sequence Diagram View. Multiple loaders can be associated to a single Sequence Diagram View. However, additional means have to be implemented to specify which loader should be used when opening the view. For example, an eclipse action or command could be used for that. This additional code is not necessary if there is only one loader for a given Sequence Diagram View associated and this loader has the attribute "default" set to "true". (see also [[#Using one Sequence Diagram View with Multiple Loaders | Using one Sequence Diagram View with Multiple Loaders]])
330 == Sequence Diagram View ==
332 For this extension point a Sequence Diagram View has to be defined as well. The Sequence Diagram View class implementation is provided by the plug-in ''org.eclipse.linuxtools.tmf.ui'' (''org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView'') and can be used as is or can also be sub-classed. For that, a view extension has to be added to the ''plugin.xml''.
334 === Supported Widgets ===
336 The loader class provides a frame containing all the UML2 widgets to be displayed. The following widgets exist:
341 *Asynchronous Message
342 *Synchronous Message Return
343 *Asynchronous Message Return
346 For a lifeline, a category can be defined. The lifeline category defines icons, which are displayed in the lifeline header.
350 The Sequence Diagram View allows the user to zoom in, zoom out and reset the zoom factor.
354 It is possible to print the whole sequence diagram as well as part of it.
358 *SHIFT+ALT+ARROW-DOWN - to scroll down within sequence diagram one view page at a time
359 *SHIFT+ALT+ARROW-UP - to scroll up within sequence diagram one view page at a time
360 *SHIFT+ALT+ARROW-RIGHT - to scroll right within sequence diagram one view page at a time
361 *SHIFT+ALT+ARROW-LEFT - to scroll left within sequence diagram one view page at a time
362 *SHIFT+ALT+ARROW-HOME - to jump to the beginning of the selected message if not already visible in page
363 *SHIFT+ALT+ARROW-END - to jump to the end of the selected message if not already visible in page
364 *CTRL+F - to open find dialog if either the basic or extended find provider is defined (see [[#Using the Find Provider Interface | Using the Find Provider Interface]])
365 *CTRL+P - to open print dialog
369 The UML2 Sequence Diagram Framework provides preferences to customize the appearance of the Sequence Diagram View. The color of all widgets and text as well as the fonts of the text of all widget can be adjust. Amongst others the default lifeline width can be alternated. To change preferences select '''Windows->Preferences->Tracing->UML2 Sequence Diagrams'''. The following preference page will show:<br>
370 [[Image:images/SeqDiagramPref.png]] <br>
371 After changing the preferences select '''OK'''.
373 === Callback hooks ===
375 The Sequence Diagram View provides several callback hooks so that extension can provide application specific functionality. The following interfaces can be provided:
376 * Basic find provider or extended find Provider<br> For finding within the sequence diagram
377 * Basic filter provider and extended Filter Provider<br> For filtering within the sequnce diagram.
378 * Basic paging provider or advanced paging provider<br> For scalability reasons, used to limit number of displayed messages
379 * Properies provider<br> To provide properties of selected elements
380 * Collapse provider <br> To collapse areas of the sequence diagram
384 This tutorial describes how to create a UML2 Sequence Diagram Loader extension and use this loader in the in Eclipse.
386 === Prerequisites ===
388 The tutorial is based on Eclipse 3.7 (Eclipse Indigo) and TMF 0.3.2.
390 === Creating an Eclipse UI Plug-in ===
392 To create a new project with name org.eclipse.linuxtools.tmf.sample.ui select '''File -> New -> Project -> Plug-in Development -> Plug-in Project'''. <br>
393 [[Image:images/Screenshot-NewPlug-inProject1.png]]<br>
395 [[Image:images/Screenshot-NewPlug-inProject2.png]]<br>
397 [[Image:images/Screenshot-NewPlug-inProject3.png]]<br>
399 === Creating a Sequence Diagram View ===
401 To open the plug-in manifest, double-click on the MANIFEST.MF file. <br>
402 [[Image:images/SelectManifest.png]]<br>
404 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.linuxtools.tmf.ui'' and press '''OK'''<br>
405 [[Image:images/AddDependencyTmfUi.png]]<br>
407 Change to the Extensions tab and select '''Add...''' of the ''All Extension'' section. A new dialog box will open. Find the view extension ''org.eclipse.ui.views'' and press '''Finish'''.<br>
408 [[Image:images/AddViewExtension1.png]]<br>
410 To create a Sequence Diagram View, click the right mouse button. Then select '''New -> view'''<br>
411 [[Image:images/AddViewExtension2.png]]<br>
413 A new view entry has been created. Fill in the fields ''id'', ''name'' and ''class''. Note that for ''class'' the SD view implementation (''org.eclipse.linuxtools.tmf.ui.views.SDView'') of the TMF UI plug-in is used.<br>
414 [[Image:images/FillSampleSeqDiagram.png]]<br>
416 The view is prepared. Run the Example. To launch the an Eclipse Application select the ''Overview'' tab and click on '''Launch an Eclipse Application'''<br>
417 [[Image:images/RunEclipseApplication.png]]<br>
419 A new Eclipse application window will show. In the new window go to '''Windows -> Show View -> Other... -> Other -> Sample Sequence Diagram'''.<br>
420 [[Image:images/ShowViewOther.png]]<br>
422 The Sequence Diagram View will open with an blank page.<br>
423 [[Image:images/BlankSampleSeqDiagram.png]]<br>
425 Close the Example Application.
427 === Defining the uml2SDLoader Extension ===
429 After defining the Sequence Diagram View it's time to create the ''uml2SDLoader'' Extension. <br>
431 Before doing that add a dependency to TMF. For that select '''Add...''' of the ''Required Plug-ins'' section. A new dialog box will open. Next find plug-in ''org.eclipse.linuxtools.tmf'' and press '''OK'''<br>
432 [[Image:images/AddDependencyTmf.png]]<br>
434 To create the loader extension, change to the Extensions tab and select '''Add...''' of the ''All Extension'' section. A new dialog box will open. Find the extension ''org.eclipse.linuxtools.tmf.ui.uml2SDLoader'' and press '''Finish'''.<br>
435 [[Image:images/AddTmfUml2SDLoader.png]]<br>
437 A new 'uml2SDLoader'' extension has been created. Fill in fields ''id'', ''name'', ''class'', ''view'' and ''default''. Use ''default'' equal true for this example. For the view add the id of the Sequence Diagram View of chapter [[#Creating a Sequence Diagram View | Creating a Sequence Diagram View]]. <br>
438 [[Image:images/FillSampleLoader.png]]<br>
440 Then click on ''class'' (see above) to open the new class dialog box. Fill in the relevant fields and select '''Finish'''. <br>
441 [[Image:images/NewSampleLoaderClass.png]]<br>
443 A new Java class will be created which implements the interface ''org.eclipse.linuxtools.tmf.ui.views.uml2sd.load.IUml2SDLoader''.<br>
446 package org.eclipse.linuxtools.tmf.sample.ui;
448 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView;
449 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.load.IUml2SDLoader;
451 public class SampleLoader implements IUml2SDLoader {
453 public SampleLoader() {
454 // TODO Auto-generated constructor stub
458 public void dispose() {
459 // TODO Auto-generated method stub
464 public String getTitleString() {
465 // TODO Auto-generated method stub
470 public void setViewer(SDView arg0) {
471 // TODO Auto-generated method stub
476 === Implementing the Loader Class ===
478 Next is to implement the methods of the IUml2SDLoader interface method. The following code snippet shows how to create the major sequence diagram elements. Please note that no time information is stored.<br>
481 package org.eclipse.linuxtools.tmf.sample.ui;
483 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView;
484 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.AsyncMessage;
485 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.AsyncMessageReturn;
486 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.ExecutionOccurrence;
487 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Frame;
488 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline;
489 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Stop;
490 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.SyncMessage;
491 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.SyncMessageReturn;
492 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.load.IUml2SDLoader;
494 public class SampleLoader implements IUml2SDLoader {
496 private SDView fSdView;
498 public SampleLoader() {
502 public void dispose() {
506 public String getTitleString() {
507 return "Sample Diagram";
511 public void setViewer(SDView arg0) {
516 private void createFrame() {
518 Frame testFrame = new Frame();
519 testFrame.setName("Sample Frame");
525 Lifeline lifeLine1 = new Lifeline();
526 lifeLine1.setName("Object1");
527 testFrame.addLifeLine(lifeLine1);
529 Lifeline lifeLine2 = new Lifeline();
530 lifeLine2.setName("Object2");
531 testFrame.addLifeLine(lifeLine2);
535 * Create Sync Message
537 // Get new occurrence on lifelines
538 lifeLine1.getNewEventOccurrence();
540 // Get Sync message instances
541 SyncMessage start = new SyncMessage();
542 start.setName("Start");
543 start.setEndLifeline(lifeLine1);
544 testFrame.addMessage(start);
547 * Create Sync Message
549 // Get new occurrence on lifelines
550 lifeLine1.getNewEventOccurrence();
551 lifeLine2.getNewEventOccurrence();
553 // Get Sync message instances
554 SyncMessage syn1 = new SyncMessage();
555 syn1.setName("Sync Message 1");
556 syn1.setStartLifeline(lifeLine1);
557 syn1.setEndLifeline(lifeLine2);
558 testFrame.addMessage(syn1);
561 * Create corresponding Sync Message Return
564 // Get new occurrence on lifelines
565 lifeLine1.getNewEventOccurrence();
566 lifeLine2.getNewEventOccurrence();
568 SyncMessageReturn synReturn1 = new SyncMessageReturn();
569 synReturn1.setName("Sync Message Return 1");
570 synReturn1.setStartLifeline(lifeLine2);
571 synReturn1.setEndLifeline(lifeLine1);
572 synReturn1.setMessage(syn1);
573 testFrame.addMessage(synReturn1);
576 * Create Activations (Execution Occurrence)
578 ExecutionOccurrence occ1 = new ExecutionOccurrence();
579 occ1.setStartOccurrence(start.getEventOccurrence());
580 occ1.setEndOccurrence(synReturn1.getEventOccurrence());
581 lifeLine1.addExecution(occ1);
582 occ1.setName("Activation 1");
584 ExecutionOccurrence occ2 = new ExecutionOccurrence();
585 occ2.setStartOccurrence(syn1.getEventOccurrence());
586 occ2.setEndOccurrence(synReturn1.getEventOccurrence());
587 lifeLine2.addExecution(occ2);
588 occ2.setName("Activation 2");
591 * Create Sync Message
593 // Get new occurrence on lifelines
594 lifeLine1.getNewEventOccurrence();
595 lifeLine2.getNewEventOccurrence();
597 // Get Sync message instances
598 AsyncMessage asyn1 = new AsyncMessage();
599 asyn1.setName("Async Message 1");
600 asyn1.setStartLifeline(lifeLine1);
601 asyn1.setEndLifeline(lifeLine2);
602 testFrame.addMessage(asyn1);
605 * Create corresponding Sync Message Return
608 // Get new occurrence on lifelines
609 lifeLine1.getNewEventOccurrence();
610 lifeLine2.getNewEventOccurrence();
612 AsyncMessageReturn asynReturn1 = new AsyncMessageReturn();
613 asynReturn1.setName("Async Message Return 1");
614 asynReturn1.setStartLifeline(lifeLine2);
615 asynReturn1.setEndLifeline(lifeLine1);
616 asynReturn1.setMessage(asyn1);
617 testFrame.addMessage(asynReturn1);
623 // Get new occurrence on lifelines
624 lifeLine1.getNewEventOccurrence();
626 EllipsisisMessage info = new EllipsisisMessage();
627 info.setName("Object deletion");
628 info.setStartLifeline(lifeLine2);
629 testFrame.addNode(info);
634 Stop stop = new Stop();
635 stop.setLifeline(lifeLine2);
636 stop.setEventOccurrence(lifeLine2.getNewEventOccurrence());
637 lifeLine2.addNode(stop);
639 fSdView.setFrame(testFrame);
644 Now it's time to run the example application. To launch the Example Application select the ''Overview'' tab and click on '''Launch an Eclipse Application'''<br>
645 [[Image:images/SampleDiagram1.png]] <br>
647 === Adding time information ===
649 To add time information in sequence diagram the timestamp has to be set for each message. The sequence diagram framework uses the ''TmfTimestamp'' class of plug-in ''org.eclipse.linuxtools.tmf''. Use ''setTime()'' on each message ''SyncMessage'' since start and end time are the same. For each ''AsyncMessage'' set start and end time separately by using methods ''setStartTime'' and ''setEndTime''. For example: <br>
652 private void createFrame() {
654 start.setTime(new TmfTimestamp(1000, -3));
655 syn1.setTime(new TmfTimestamp(1005, -3));
656 synReturn1.setTime(new TmfTimestamp(1050, -3));
657 asyn1.setStartTime(new TmfTimestamp(1060, -3));
658 asyn1.setEndTime(new TmfTimestamp(1070, -3));
659 asynReturn1.setStartTime(new TmfTimestamp(1060, -3));
660 asynReturn1.setEndTime(new TmfTimestamp(1070, -3));
665 When running the example application, a time compression bar on the left appears which indicates the time elapsed between consecutive events. The time compression scale shows where the time falls between the minimum and maximum delta times. The intensity of the color is used to indicate the length of time, namely, the deeper the intensity, the higher the delta time. The minimum and maximum delta times are configurable through the collbar menu ''Configure Min Max''. The time compression bar and scale may provide an indication about which events consumes the most time. By hovering over the time compression bar a tooltip appears containing more information. <br>
667 [[Image:images/SampleDiagramTimeComp.png]] <br>
669 By hovering over a message it will show the time information in the appearing tooltip. For each ''SyncMessage'' it shows its time occurrence and for each ''AsyncMessage'' it shows the start and end time.
671 [[Image:images/SampleDiagramSyncMessage.png]] <br>
672 [[Image:images/SampleDiagramAsyncMessage.png]] <br>
674 To see the time elapsed between 2 messages, select one message and hover over a second message. A tooltip will show with the delta in time. Note if the second message is before the first then a negative delta is displayed. Note that for ''AsynMessage'' the end time is used for the delta calculation.<br>
675 [[Image:images/SampleDiagramMessageDelta.png]] <br>
677 === Default Coolbar and Menu Items ===
679 The Sequence Diagram View comes with default coolbar and menu items. By default, each sequence diagram shows the following actions:
684 * Configure Min Max (drop-down menu only)
685 * Navigation -> Show the node end (drop-down menu only)
686 * Navigation -> Show the node start (drop-down menu only)
688 [[Image:images/DefaultCoolbarMenu.png]]<br>
690 === Implementing Optional Callbacks ===
692 The following chapters describe how to use all supported provider interfaces.
694 ==== Using the Paging Provider Interface ====
696 For scalability reasons, the paging provider interfaces exists to limit the number of messages displayed in the Sequence Diagram View at a time. For that, two interfaces exist, the basic paging provider and the advanced paging provider. When using the basic paging interface, actions for traversing page by page through the sequence diagram of a trace will be provided.
698 To use the basic paging provider, first the interface methods of the ''ISDPagingProvider'' have to be implemented by a class. (i.e. ''hasNextPage()'', ''hasPrevPage()'', ''nextPage()'', ''prevPage()'', ''firstPage()'' and ''endPage()''. Typically, this is implemented in the loader class. Secondly, the provider has to be set in the Sequence Diagram View. This will be done in the ''setViewer()'' method of the loader class. Lastly, the paging provider has to be removed from the view, when the ''dispose()'' method of the loader class is called.
701 public class SampleLoader implements IUml2SDLoader, ISDPagingProvider {
706 public void dispose() {
707 if (fSdView != null) {
708 fSdView.resetProviders();
713 public void setViewer(SDView arg0) {
715 fSdView.setSDPagingProvider(this);
719 private void createSecondFrame() {
720 Frame testFrame = new Frame();
721 testFrame.setName("SecondFrame");
722 Lifeline lifeline = new Lifeline();
723 lifeline.setName("LifeLine 0");
724 testFrame.addLifeLine(lifeline);
725 lifeline = new Lifeline();
726 lifeline.setName("LifeLine 1");
727 testFrame.addLifeLine(lifeline);
728 for (int i = 1; i < 5; i++) {
729 SyncMessage message = new SyncMessage();
730 message.autoSetStartLifeline(testFrame.getLifeline(0));
731 message.autoSetEndLifeline(testFrame.getLifeline(0));
732 message.setName((new StringBuilder("Message ")).append(i).toString());
733 testFrame.addMessage(message);
735 SyncMessageReturn messageReturn = new SyncMessageReturn();
736 messageReturn.autoSetStartLifeline(testFrame.getLifeline(0));
737 messageReturn.autoSetEndLifeline(testFrame.getLifeline(0));
739 testFrame.addMessage(messageReturn);
740 messageReturn.setName((new StringBuilder("Message return ")).append(i).toString());
741 ExecutionOccurrence occ = new ExecutionOccurrence();
742 occ.setStartOccurrence(testFrame.getSyncMessage(i - 1).getEventOccurrence());
743 occ.setEndOccurrence(testFrame.getSyncMessageReturn(i - 1).getEventOccurrence());
744 testFrame.getLifeline(0).addExecution(occ);
746 fSdView.setFrame(testFrame);
750 public boolean hasNextPage() {
755 public boolean hasPrevPage() {
760 public void nextPage() {
766 public void prevPage() {
772 public void firstPage() {
778 public void lastPage() {
787 When running the example application, new actions will be shown in the coolbar and the coolbar menu. <br>
789 [[Image:images/PageProviderAdded.png]]
792 To use the advanced paging provider, the interface ''ISDAdvancePagingProvider'' has to be implemented. It extends the basic paging provider. The methods ''currentPage()'', ''pagesCount()'' and ''pageNumberChanged()'' have to be added.
795 ==== Using the Find Provider Interface ====
797 For finding nodes in a sequence diagram two interfaces exists. One for basic finding and one for extended finding. The basic find comes with a dialog box for entering find criteria as regular expressions. This find criteria can be used to execute the find. Find criteria a persisted in the Eclipse workspace.
799 For the extended find provider interface a ''org.eclipse.jface.action.Action'' class has to be provided. The actual find handling has to be implemented and triggered by the action.
801 Only on at a time can be active. If the extended find provder is defined it obsoletes the basic find provider.
803 To use the basic find provider, first the interface methods of the ''ISDFindProvider'' have to be implemented by a class. Typically, this is implemented in the loader class. Add the ISDFindProvider to the list of implemented interfaces, implement the methods ''find()'' and ''cancel()'' and set the provider in the ''setViewer()'' method as well as remove the provider in the ''dispose()'' method of the loader class. Please note that the ''ISDFindProvider'' extends the interface ''ISDGraphNodeSupporter'' which methods (''isNodeSupported()'' and ''getNodeName()'') have to be implemented, too. The following shows an example implementation. Please note that only search for lifelines and SynchMessage are supported. The find itself will always find only the first occurrence the pattern to match.
806 public class SampleLoader implements IUml2SDLoader, ISDPagingProvider, ISDFindProvider {
810 public void dispose() {
811 if (fSdView != null) {
812 fSdView.resetProviders();
817 public void setViewer(SDView arg0) {
819 fSdView.setSDPagingProvider(this);
820 fSdView.setSDFindProvider(this);
825 public boolean isNodeSupported(int nodeType) {
827 case ISDGraphNodeSupporter.LIFELINE:
828 case ISDGraphNodeSupporter.SYNCMESSAGE:
838 public String getNodeName(int nodeType, String loaderClassName) {
840 case ISDGraphNodeSupporter.LIFELINE:
842 case ISDGraphNodeSupporter.SYNCMESSAGE:
843 return "Sync Message";
849 public boolean find(Criteria criteria) {
850 Frame frame = fSdView.getFrame();
851 if (criteria.isLifeLineSelected()) {
852 for (int i = 0; i < frame.lifeLinesCount(); i++) {
853 if (criteria.matches(frame.getLifeline(i).getName())) {
854 fSdView.getSDWidget().moveTo(frame.getLifeline(i));
859 if (criteria.isSyncMessageSelected()) {
860 for (int i = 0; i < frame.syncMessageCount(); i++) {
861 if (criteria.matches(frame.getSyncMessage(i).getName())) {
862 fSdView.getSDWidget().moveTo(frame.getSyncMessage(i));
871 public void cancel() {
872 // reset find parameters
878 When running the example application, the find action will be shown in the coolbar and the coolbar menu. <br>
879 [[Image:images/FindProviderAdded.png]]
881 To find a sequence diagram node press on the find button of the coolbar (see above). A new dialog box will open. Enter a regular expression in the ''Matching String'' text box, select the node types (e.g. Sync Message) and press '''Find'''. If found the corresponding node will be selected. If not found the dialog box will indicate not found. <br>
882 [[Image:images/FindDialog.png]]<br>
884 Note that the find dialog will be opened by typing the key shortcut CRTL+F.
886 ==== Using the Filter Provider Interface ====
888 For filtering of sequence diagram elements two interfaces exists. One basic for filtering and one for extended filtering. The basic filtering comes with two dialog for entering filter criteria as regular expressions and one for selecting the filter to be used. Multiple filters can be active at a time. Filter criteria are persisted in the Eclipse workspace.
890 To use the basic filter provider, first the interface method of the ''ISDFilterProvider'' has to be implemented by a class. Typically, this is implemented in the loader class. Add the ''ISDFilterProvider'' to the list of implemented interfaces, implement the method ''filter()''and set the provider in the ''setViewer()'' method as well as remove the provider in the ''dispose()'' method of the loader class. Please note that the ''ISDFindProvider'' extends the interface ''ISDGraphNodeSupporter'' which methods (''isNodeSupported()'' and ''getNodeName()'') have to be implemented, too. <br>
891 Note that no example implementation of ''filter()'' is provided.
895 public class SampleLoader implements IUml2SDLoader, ISDPagingProvider, ISDFindProvider, ISDFilterProvider {
899 public void dispose() {
900 if (fSdView != null) {
901 fSdView.resetProviders();
906 public void setViewer(SDView arg0) {
908 fSdView.setSDPagingProvider(this);
909 fSdView.setSDFindProvider(this);
910 fSdView.setSDFilterProvider(this);
915 public boolean filter(List<?> list) {
922 When running the example application, the filter action will be shown in the coolbar menu. <br>
923 [[Image:images/HidePatternsMenuItem.png]]
925 To filter select the '''Hide Patterns...''' of the coolbar menu. A new dialog box will open. <br>
926 [[Image:images/DialogHidePatterns.png]]
928 To Add a new filter press '''Add...'''. A new dialog box will open. Enter a regular expression in the ''Matching String'' text box, select the node types (e.g. Sync Message) and press '''Create''''. <br>
929 [[Image:images/DialogHidePatterns.png]] <br>
931 Now back at the Hide Pattern dialog. Select one or more filter and select '''OK'''.
933 To use the extended filter provider, the interface ''ISDExtendedFilterProvider'' has to be implemented. It will provide a ''org.eclipse.jface.action.Action'' class containing the actual filter handling and filter algorithm.
935 ==== Using the Extended Action Bar Provider Interface ====
937 The extended action bar provider can be used to add customized actions to the Sequence Diagram View.
938 To use the extended action bar provider, first the interface method of the interface ''ISDExtendedActionBarProvider'' has to be implemented by a class. Typically, this is implemented in the loader class. Add the ''ISDExtendedActionBarProvider'' to the list of implemented interfaces, implement the method ''supplementCoolbarContent()'' and set the provider in the ''setViewer()'' method as well as remove the provider in the ''dispose()'' method of the loader class. <br>
941 public class SampleLoader implements IUml2SDLoader, ISDPagingProvider, ISDFindProvider, ISDFilterProvider, ISDExtendedActionBarProvider {
945 public void dispose() {
946 if (fSdView != null) {
947 fSdView.resetProviders();
952 public void setViewer(SDView arg0) {
954 fSdView.setSDPagingProvider(this);
955 fSdView.setSDFindProvider(this);
956 fSdView.setSDFilterProvider(this);
957 fSdView.setSDExtendedActionBarProvider(this);
962 public void supplementCoolbarContent(IActionBars iactionbars) {
963 Action action = new Action("Refresh") {
966 System.out.println("Refreshing...");
969 iactionbars.getMenuManager().add(action);
970 iactionbars.getToolBarManager().add(action);
976 When running the example application, all new actions will be added to the coolbar and coolbar menu according to the implementation of ''supplementCoolbarContent()''<br>.
977 For the example above the coolbar and coolbar menu will look as follows.
979 [[Image:images/SupplCoolbar.png]]
981 ==== Using the Properties Provider Interface====
983 This interface can be used to provide property information. A property provider which returns an ''IPropertyPageSheet'' (see ''org.eclipse.ui.views'') has to be implemented and set in the Sequence Diagram View. <br>
985 To use the property provider, first the interface method of the ''ISDPropertiesProvider'' has to be implemented by a class. Typically, this is implemented in the loader class. Add the ''ISDPropertiesProvider'' to the list of implemented interfaces, implement the method ''getPropertySheetEntry()'' and set the provider in the ''setViewer()'' method as well as remove the provider in the ''dispose()'' method of the loader class. Please note that no example is provided here.
987 Please refer to the following Eclipse articles for more information about properties and tabed properties.
988 *[http://www.eclipse.org/articles/Article-Properties-View/properties-view.html | Take control of your properties]
989 *[http://www.eclipse.org/articles/Article-Tabbed-Properties/tabbed_properties_view.html | The Eclipse Tabbed Properties View]
991 ==== Using the Collapse Provider Interface ====
993 This interface can be used to define a provider which responsibility is to collapse two selected lifelines. This can be used to hide a pair of lifelines.
995 To use the collapse provider, first the interface method of the ''ISDCollapseProvider'' has to be implemented by a class. Typically, this is implemented in the loader class. Add the ISDCollapseProvider to the list of implemented interfaces, implement the method ''collapseTwoLifelines()'' and set the provider in the ''setViewer()'' method as well as remove the provider in the ''dispose()'' method of the loader class. Please note that no example is provided here.
997 ==== Using the Selection Provider Service ====
999 The Sequence Diagram View comes with a build in selection provider service. To this service listeners can be added. To use the selection provider service, the interface ''ISelectionListener'' of plug-in ''org.eclipse.ui'' has to implemented. Typically this is implemented in loader class. Firstly, add the ''ISelectionListener'' interface to the list of implemented interfaces, implement the method ''selectionChanged()'' and set the listener in method ''setViewer()'' as well as remove the listener in the ''dispose()'' method of the loader class.
1002 public class SampleLoader implements IUml2SDLoader, ISDPagingProvider, ISDFindProvider, ISDFilterProvider, ISDExtendedActionBarProvider, ISelectionListener {
1006 public void dispose() {
1007 if (fSdView != null) {
1008 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().removePostSelectionListener(this);
1009 fSdView.resetProviders();
1014 public String getTitleString() {
1015 return "Sample Diagram";
1019 public void setViewer(SDView arg0) {
1021 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().addPostSelectionListener(this);
1022 fSdView.setSDPagingProvider(this);
1023 fSdView.setSDFindProvider(this);
1024 fSdView.setSDFilterProvider(this);
1025 fSdView.setSDExtendedActionBarProvider(this);
1031 public void selectionChanged(IWorkbenchPart part, ISelection selection) {
1032 ISelection sel = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
1033 if (sel != null && (sel instanceof StructuredSelection)) {
1034 StructuredSelection stSel = (StructuredSelection) sel;
1035 if (stSel.getFirstElement() instanceof BaseMessage) {
1036 BaseMessage syncMsg = ((BaseMessage) stSel.getFirstElement());
1037 System.out.println("Message '" + syncMsg.getName() + "' selected.");
1046 === Printing a Sequence Diagram ===
1048 To print a the whole sequence diagram or only parts of it, select the Sequence Diagram View and select '''File -> Print...''' or type the key combination ''CTRL+P''. A new print dialog will open. <br>
1050 [[Image:images/PrintDialog.png]] <br>
1052 Fill in all the relevant information, select '''Printer...''' to choose the printer and the press '''OK'''.
1054 === Using one Sequence Diagram View with Multiple Loaders ===
1056 A Sequence Diagram View definition can be used with multiple sequence diagram loaders. However, the active loader to be used when opening the view has to be set. For this define an Eclipse action or command and assign the current loader to the view. Here is a code snippet for that:
1059 public class OpenSDView extends AbstractHandler {
1061 public Object execute(ExecutionEvent event) throws ExecutionException {
1063 IWorkbenchPage persp = TmfUiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
1064 SDView view = (SDView) persp.showView("org.eclipse.linuxtools.ust.examples.ui.componentinteraction");
1065 LoadersManager.getLoadersManager().createLoader("org.eclipse.linuxtools.tmf.ui.views.uml2sd.impl.TmfUml2SDSyncLoader", view);
1066 } catch (PartInitException e) {
1067 throw new ExecutionException("PartInitException caught: ", e);
1074 === Downloading the Tutorial ===
1076 Use the following link to download the source code of the tutorial [http://wiki.eclipse.org/images/e/e6/SamplePlugin.zip Plug-in of Tutorial].
1078 == Integration of Tracing and Monitoring Framework with Sequence Diagram Framework ==
1080 In the previous sections the Sequence Diagram Framework has been described and a tutorial was provided. In the following sections the integration of the Sequence Diagram Framework with other features of TMF will be described. Together it is a powerful framework to analyze and visualize content of traces. The integration is explained using the reference implementation of a UML2 sequence diagram loader which part of the TMF UI delivery. The reference implementation can be used as is, can be sub-classed or simply be an example for other sequence diagram loaders to be implemented.
1082 === Reference Implementation ===
1084 A Sequence Diagram View Extension is defined in the plug-in TMF UI as well as a uml2SDLoader Extension with the reference loader.
1086 [[Image:images/ReferenceExtensions.png]]
1088 === Used Sequence Diagram Features ===
1090 Besides the default features of the Sequence Diagram Framework, the reference implementation uses the following additional features:
1096 ==== Advanced paging ====
1098 The reference loader implements the interface ''ISDAdvancedPagingProvider'' interface. Please refer to section [[#Using the Paging Provider Interface | Using the Paging Provider Interface]] for more details about the advanced paging feature.
1100 ==== Basic finding ====
1102 The reference loader implements the interface ''ISDFindProvider'' interface. The user can search for ''Lifelines'' and ''Interactions''. The find is done across pages. If the expression to match is not on the current page a new thread is started to search on other pages. If expression is found the corresponding page is shown as well as the searched item is displayed. If not found then a message is displayed in the ''Progress View'' of Eclipse. Please refer to section [[#Using the Find Provider Interface | Using the Find Provider Interface]] for more details about the basic find feature.
1104 ==== Basic filtering ====
1106 The reference loader implements the interface ''ISDFilterProvider'' interface. The user can filter on ''Lifelines'' and ''Interactions''. Please refer to section [[#Using the Filter Provider Interface | Using the Filter Provider Interface]] for more details about the basic filter feature.
1108 ==== Selection Service ====
1110 The reference loader implements the interface ''ISelectionListener'' interface. When an interaction is selected a ''TmfTimeSynchSignal'' is broadcast (see [[#TMF Signal Framework | TMF Signal Framework]]). Please also refer to section [[#Using the Selection Provider Service | Using the Selection Provider Service]] for more details about the selection service and .
1112 === Used TMF Features ===
1114 The reference implementation uses the following features of TMF:
1115 *TMF Experiment and Trace for accessing traces
1116 *Event Request Framework to request TMF events from the experiment and respective traces
1117 *Signal Framework for broadcasting and receiving TMF signals for synchronization purposes
1119 ==== TMF Experiment and Trace for accessing traces ====
1121 The reference loader uses TMF Experiments to access traces and to request data from the traces.
1123 ==== TMF Event Request Framework ====
1125 The reference loader use the TMF Event Request Framework to request events from the experiment and its traces.
1127 When opening a traces (which is triggered by signal ''TmfExperimentSelected'') or when opening the Sequence Diagram View after a trace had been opened previously, a TMF background request is initiated to index the trace and to fill in the first page of the sequence diagram. The purpose of the indexing is to store time ranges for pages with 10000 messages per page. This allows quickly to move to certain pages in a trace without having to re-parse from the beginning. The request is called indexing request.
1129 When switching pages, the a TMF foreground event request is initiated to retrieve the corresponding events from the experiment. It uses the time range stored in the index for the respective page.
1131 A third type of event request is issued for finding specific data across pages.
1133 ==== TMF Signal Framework ====
1135 The reference loader extends the class ''TmfComponent''. By doing that the loader is register as TMF signal handler for sending and receiving TMF signals. The loader implements signal handlers for the following TMF signals:
1136 *''TmfTraceSelectedSignal''
1137 This signal indicates that a trace or experiment was selected. When receiving this signal the indexing request is initiated and the first page is displayed after receiving the relevant information.
1139 This signal indicates that a trace or experiment was closed. When receiving this signal the loader resets its data and a blank page is loaded in the Sequence Diagram View.
1140 *''TmfTimeSynchSignal''
1141 This signal indicates that a event with a certain timestamp is selected. When receiving this signal the corresponding message is selected in the Sequence Diagram View. If necessary, the page is changed.
1142 *''TmfRangeSynchSignal''
1143 This signal indicates that a new time range is in focus. When receiving this signal the loader loads the page which corresponds to the start time of the time range signal. The message with the start time will be in focus.
1145 Besides acting on receiving signals, the reference loader is also sending signals. A ''TmfTimeSynchSignal'' is broadcasted with the timestamp of the message which was selected in the Sequence Diagram View. ''TmfRangeSynchSignal'' is sent when a page is changed in the Sequence Diagram View. The start timestamp of the time range sent is the timestamp of the first message. The end timestamp sent is the timestamp of the first message plus the current time range window. The current time range window is the time window that was indicated in the last received ''TmfRangeSynchSignal''.
1147 === Supported Traces ===
1149 The reference implementation is able to analyze traces from a single component that traces the interaction with other components. For example, a server node could have trace information about its interaction with client nodes. The server node could be traced and then analyzed using TMF and the Sequence Diagram Framework of TMF could used to visualize the interactions with the client nodes.<br>
1151 Note that combined traces of multiple components, that contain the trace information about the same interactions are not supported in the reference implementation!
1153 === Trace Format ===
1155 The reference implementation in class ''TmfUml2SDSyncLoader'' in package ''org.eclipse.linuxtools.tmf.ui.views.uml2sd.impl'' analyzes events from type ''ITmfEvent'' and creates events type ''ITmfSyncSequenceDiagramEvent'' if the ''ITmfEvent'' contains all relevant information information. The parsing algorithm looks like as follows:
1159 * @param tmfEvent Event to parse for sequence diagram event details
1160 * @return sequence diagram event if details are available else null
1162 protected ITmfSyncSequenceDiagramEvent getSequenceDiagramEvent(ITmfEvent tmfEvent){
1163 //type = .*RECEIVE.* or .*SEND.*
1164 //content = sender:<sender name>:receiver:<receiver name>,signal:<signal name>
1165 String eventType = tmfEvent.getType().toString();
1166 if (eventType.contains(Messages.TmfUml2SDSyncLoader_EventTypeSend) || eventType.contains(Messages.TmfUml2SDSyncLoader_EventTypeReceive)) {
1167 Object sender = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldSender);
1168 Object receiver = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldReceiver);
1169 Object name = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldSignal);
1170 if ((sender instanceof ITmfEventField) && (receiver instanceof ITmfEventField) && (name instanceof ITmfEventField)) {
1171 ITmfSyncSequenceDiagramEvent sdEvent = new TmfSyncSequenceDiagramEvent(tmfEvent,
1172 ((ITmfEventField) sender).getValue().toString(),
1173 ((ITmfEventField) receiver).getValue().toString(),
1174 ((ITmfEventField) name).getValue().toString());
1183 The analysis looks for event type Strings containing ''SEND'' and ''RECEIVE''. If event type matches these key words, the analyzer will look for strings ''sender'', ''receiver'' and ''signal'' in the event fields of type ''ITmfEventField''. If all the data is found a sequence diagram event from can be created. Note that Sync Messages are assumed, which means start and end time are the same.
1185 === How to use the Reference Implementation ===
1187 An example trace visualizer is provided that uses a trace in binary format. It contains trace events with sequence diagram information. To parse the data using TMF a class is provided that implements ''ITmfTrace''. Additionally, a parser is provided that reads from the file and converts a trace event to ''TmfEvent''. This parser implements the interface ''ITmfEventParser''. To get the source code see [[#Downloading the Reference Plug-in | Download the Reference Plug-in]]
1189 The plug-in structure will look like this:<br>
1190 [[Image:images/ReferencePlugin.png]]<br>
1192 To open the plug-in manifest, double-click on the MANIFEST.MF file. <br>
1193 [[Image:images/SelectManifestRef.png]]<br>
1195 Run the Reference Application. To launch the Eclipse Application select the ''Overview'' tab and click on '''Launch an Eclipse Application'''<br>
1196 [[Image:images/RunApplicationRef.png]]<br>
1198 To open the Reference Sequence Diagram View, select '''Windows -> Show View -> Other... -> TMF -> Sequence Diagram''' <br>
1199 [[Image:images/ShowTmfSDView.png]]<br>
1201 An blank Sequence Diagram View will open.
1203 Select the '''Select Experiment''' button of the toolbar to load the sequence diagram from the data provided in the trace file. What this does is open the file ''tracesets/sdEvents'', parse this file through TMF and analyze all events of type ''TmfEvent'' and generates the Sequence Diagram out of it. <br>
1204 [[Image:images/ReferenceSeqDiagram.png]]<br>
1206 Now the reference application can be explored. To demonstrate the view features try the following things:
1207 *Select a message in the Sequence diagram. As result the corresponding event will be selected in the Events View.
1208 *Select an event in the Events View. As result the corresponding message in the Sequence Diagram View will be selected. If necessary, the page will be changed.
1209 *In the Events View, press key ''End''. As result, the Sequence Diagram view will jump to the last page.
1210 *In the Events View, press key ''Home''. As result, the Sequence Diagram view will jump to the first page.
1211 *In the Sequence Diagram View select the find button. Enter the expression '''REGISTER.*''', select '''Search for Interaction''' and press '''Find'''. As result the corresponding message will be selected in the Sequence Diagram and the corresponding event in the Events View will be selected. Select again '''Find''' the next occurrence of will be selected. Since the second occurrence is on a different page than the first, the corresponding page will be loaded.
1212 * In the Sequence Diagram View, select menu item '''Hide Patterns...'''. Add the filter '''BALL.*''' for '''Interaction''' only and select '''OK'''. As result all messages with name ''BALL_REQUEST'' and ''BALL_REPLY'' will be hidden. To remove the filter, select menu item '''Hide Patterns...''', deselect the corresponding filter and press '''OK'''. All the messages will be shown again.<br>
1214 To dispose the diagram, select the '''Dispose Experiment''' button of the toolbar. The current sequence diagram will be disposed and an empty diagram will be loaded.
1216 === Extending the Reference Loader ===
1218 In some case it might be necessary to change the implementation of the analysis of each ''TmfEvent'' for the generation of ''Sequence Diagram Events''. For that just extend the class ''TmfUml2SDSyncLoader'' and overwrite the method ''protected ITmfSyncSequenceDiagramEvent getSequnceDiagramEvent(TmfEvent tmfEvent)'' with your own implementation.
1220 === Downloading the Reference Plug-in ===
1221 To download the reference plug-in that demonstrates the reference loader, use the following link: [http://wiki.eclipse.org/images/d/d3/ReferencePlugin.zip Reference Plug-in]. Just extract the zip file and import the extracted Eclipse plug-in (plug-in name: ''org.eclipse.linuxtools.tmf.reference.ui'') to your Eclipse workspace. <br>
1225 This tutorial describes how to create a simple view using the TMF framework and the SWTChart library. SWTChart is a library based on SWT that can draw several types of charts including a line chart which we will use in this tutorial. We will create a view containing a line chart that displays time stamps on the X axis and the corresponding event values on the Y axis.
1227 This tutorial will cover concepts like:
1230 * Signal handling (@TmfSignalHandler)
1231 * Data requests (TmfEventRequest)
1232 * SWTChart integration
1234 === Prerequisites ===
1236 The tutorial is based on Eclipse 4.3 (Eclipse Kepler), TMF 2.0.0 and SWTChart 0.7.0. You can install SWTChart by using the Orbit update site. http://download.eclipse.org/tools/orbit/downloads/
1238 === Creating an Eclipse UI Plug-in ===
1240 To create a new project with name org.eclipse.linuxtools.tmf.sample.ui select '''File -> New -> Project -> Plug-in Development -> Plug-in Project'''. <br>
1241 [[Image:images/Screenshot-NewPlug-inProject1.png]]<br>
1243 [[Image:images/Screenshot-NewPlug-inProject2.png]]<br>
1245 [[Image:images/Screenshot-NewPlug-inProject3.png]]<br>
1247 === Creating a View ===
1249 To open the plug-in manifest, double-click on the MANIFEST.MF file. <br>
1250 [[Image:images/SelectManifest.png]]<br>
1252 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.linuxtools.tmf.core'' and press '''OK'''<br>
1253 Following the same steps, add ''org.eclipse.linuxtools.tmf.ui'' and ''org.swtchart''.<br>
1254 [[Image:images/AddDependencyTmfUi.png]]<br>
1256 Change to the Extensions tab and select '''Add...''' of the ''All Extension'' section. A new dialog box will open. Find the view extension ''org.eclipse.ui.views'' and press '''Finish'''.<br>
1257 [[Image:images/AddViewExtension1.png]]<br>
1259 To create a view, click the right mouse button. Then select '''New -> view'''<br>
1260 [[Image:images/AddViewExtension2.png]]<br>
1262 A new view entry has been created. Fill in the fields ''id'' and ''name''. For ''class'' click on the '''class hyperlink''' and it will show the New Java Class dialog. Enter the name ''SampleView'', change the superclass to ''TmfView'' and click Finish. This will create the source file and fill the ''class'' field in the process. We use TmfView as the superclass because it provides extra functionality like getting the active trace, pinning and it has support for signal handling between components.<br>
1263 [[Image:images/FillSampleViewExtension.png]]<br>
1265 This will generate an empty class. Once the quick fixes are applied, the following code is obtained:
1268 package org.eclipse.linuxtools.tmf.sample.ui;
1270 import org.eclipse.swt.widgets.Composite;
1271 import org.eclipse.ui.part.ViewPart;
1273 public class SampleView extends TmfView {
1275 public SampleView(String viewName) {
1277 // TODO Auto-generated constructor stub
1281 public void createPartControl(Composite parent) {
1282 // TODO Auto-generated method stub
1287 public void setFocus() {
1288 // TODO Auto-generated method stub
1295 This creates an empty view, however the basic structure is now is place.
1297 ===Implementing a view===
1299 We will start by adding a empty chart then it will need to be populated with the trace data. Finally, we will make the chart more visually pleasing by adjusting the range and formating the time stamps.
1301 ====Adding an Empty Chart====
1303 First, we can add an empty chart to the view and initialize some of its components.
1306 private static final String SERIES_NAME = "Series";
1307 private static final String Y_AXIS_TITLE = "Signal";
1308 private static final String X_AXIS_TITLE = "Time";
1309 private static final String FIELD = "value"; // The name of the field that we want to display on the Y axis
1310 private static final String VIEW_ID = "org.eclipse.linuxtools.tmf.sample.ui.view";
1311 private Chart chart;
1312 private ITmfTrace currentTrace;
1314 public SampleView() {
1319 public void createPartControl(Composite parent) {
1320 chart = new Chart(parent, SWT.BORDER);
1321 chart.getTitle().setVisible(false);
1322 chart.getAxisSet().getXAxis(0).getTitle().setText(X_AXIS_TITLE);
1323 chart.getAxisSet().getYAxis(0).getTitle().setText(Y_AXIS_TITLE);
1324 chart.getSeriesSet().createSeries(SeriesType.LINE, SERIES_NAME);
1325 chart.getLegend().setVisible(false);
1329 public void setFocus() {
1334 The view is prepared. Run the Example. To launch the an Eclipse Application select the ''Overview'' tab and click on '''Launch an Eclipse Application'''<br>
1335 [[Image:images/RunEclipseApplication.png]]<br>
1337 A new Eclipse application window will show. In the new window go to '''Windows -> Show View -> Other... -> Other -> Sample View'''.<br>
1338 [[Image:images/ShowViewOther.png]]<br>
1340 You should now see a view containing an empty chart<br>
1341 [[Image:images/EmptySampleView.png]]<br>
1343 ====Signal Handling====
1345 We would like to populate the view when a trace is selected. To achieve this, we can use a signal hander which is specified with the '''@TmfSignalHandler''' annotation.
1349 public void traceSelected(final TmfTraceSelectedSignal signal) {
1354 ====Requesting Data====
1356 Then we need to actually gather data from the trace. This is done asynchronously using a ''TmfEventRequest''
1360 public void traceSelected(final TmfTraceSelectedSignal signal) {
1361 // Don't populate the view again if we're already showing this trace
1362 if (currentTrace == signal.getTrace()) {
1365 currentTrace = signal.getTrace();
1367 // Create the request to get data from the trace
1369 TmfEventRequest req = new TmfEventRequest(TmfEvent.class,
1370 TmfTimeRange.ETERNITY, TmfEventRequest.ALL_DATA,
1371 ExecutionType.BACKGROUND) {
1374 public void handleData(ITmfEvent data) {
1375 // Called for each event
1376 super.handleData(data);
1380 public void handleSuccess() {
1381 // Request successful, not more data available
1382 super.handleSuccess();
1386 public void handleFailure() {
1387 // Request failed, not more data available
1388 super.handleFailure();
1391 ITmfTrace trace = signal.getTrace();
1392 trace.sendRequest(req);
1396 ====Transferring Data to the Chart====
1398 The chart expects an array of doubles for both the X and Y axis values. To provide that, we can accumulate each event's time and value in their respective list then convert the list to arrays when all events are processed.
1401 TmfEventRequest req = new TmfEventRequest(TmfEvent.class,
1402 TmfTimeRange.ETERNITY, TmfEventRequest.ALL_DATA,
1403 ExecutionType.BACKGROUND) {
1405 ArrayList<Double> xValues = new ArrayList<Double>();
1406 ArrayList<Double> yValues = new ArrayList<Double>();
1409 public void handleData(ITmfEvent data) {
1410 // Called for each event
1411 super.handleData(data);
1412 ITmfEventField field = data.getContent().getField(FIELD);
1413 if (field != null) {
1414 yValues.add((Double) field.getValue());
1415 xValues.add((double) data.getTimestamp().getValue());
1420 public void handleSuccess() {
1421 // Request successful, not more data available
1422 super.handleSuccess();
1424 final double x[] = toArray(xValues);
1425 final double y[] = toArray(yValues);
1427 // This part needs to run on the UI thread since it updates the chart SWT control
1428 Display.getDefault().asyncExec(new Runnable() {
1432 chart.getSeriesSet().getSeries()[0].setXSeries(x);
1433 chart.getSeriesSet().getSeries()[0].setYSeries(y);
1442 * Convert List<Double> to double[]
1444 private double[] toArray(List<Double> list) {
1445 double[] d = new double[list.size()];
1446 for (int i = 0; i < list.size(); ++i) {
1455 ====Adjusting the Range====
1457 The chart now contains values but they might be out of range and not visible. We can adjust the range of each axis by computing the minimum and maximum values as we add events.
1461 ArrayList<Double> xValues = new ArrayList<Double>();
1462 ArrayList<Double> yValues = new ArrayList<Double>();
1463 private double maxY = -Double.MAX_VALUE;
1464 private double minY = Double.MAX_VALUE;
1465 private double maxX = -Double.MAX_VALUE;
1466 private double minX = Double.MAX_VALUE;
1469 public void handleData(ITmfEvent data) {
1470 super.handleData(data);
1471 ITmfEventField field = data.getContent().getField(FIELD);
1472 if (field != null) {
1473 Double yValue = (Double) field.getValue();
1474 minY = Math.min(minY, yValue);
1475 maxY = Math.max(maxY, yValue);
1476 yValues.add(yValue);
1478 double xValue = (double) data.getTimestamp().getValue();
1479 xValues.add(xValue);
1480 minX = Math.min(minX, xValue);
1481 maxX = Math.max(maxX, xValue);
1486 public void handleSuccess() {
1487 super.handleSuccess();
1488 final double x[] = toArray(xValues);
1489 final double y[] = toArray(yValues);
1491 // This part needs to run on the UI thread since it updates the chart SWT control
1492 Display.getDefault().asyncExec(new Runnable() {
1496 chart.getSeriesSet().getSeries()[0].setXSeries(x);
1497 chart.getSeriesSet().getSeries()[0].setYSeries(y);
1499 // Set the new range
1500 if (!xValues.isEmpty() && !yValues.isEmpty()) {
1501 chart.getAxisSet().getXAxis(0).setRange(new Range(0, x[x.length - 1]));
1502 chart.getAxisSet().getYAxis(0).setRange(new Range(minY, maxY));
1504 chart.getAxisSet().getXAxis(0).setRange(new Range(0, 1));
1505 chart.getAxisSet().getYAxis(0).setRange(new Range(0, 1));
1507 chart.getAxisSet().adjustRange();
1515 ====Formatting the Time Stamps====
1517 To display the time stamps on the X axis nicely, we need to specify a format or else the time stamps will be displayed as ''long''. We use TmfTimestampFormat to make it consistent with the other TMF views. We also need to handle the '''TmfTimestampFormatUpdateSignal''' to make sure that the time stamps update when the preferences change.
1521 public void createPartControl(Composite parent) {
1524 chart.getAxisSet().getXAxis(0).getTick().setFormat(new TmfChartTimeStampFormat());
1527 public class TmfChartTimeStampFormat extends SimpleDateFormat {
1528 private static final long serialVersionUID = 1L;
1530 public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
1531 long time = date.getTime();
1532 toAppendTo.append(TmfTimestampFormat.getDefaulTimeFormat().format(time));
1538 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
1539 // Called when the time stamp preference is changed
1540 chart.getAxisSet().getXAxis(0).getTick().setFormat(new TmfChartTimeStampFormat());
1545 We also need to populate the view when a trace is already selected and the view is opened. We can reuse the same code by having the view send the '''TmfTraceSelectedSignal''' to itself.
1549 public void createPartControl(Composite parent) {
1552 ITmfTrace trace = getActiveTrace();
1553 if (trace != null) {
1554 traceSelected(new TmfTraceSelectedSignal(this, trace));
1559 The view is now ready but we need a proper trace to test it. For this example, a trace was generated using LTTng-UST so that it would produce a sine function.<br>
1561 [[Image:images/SampleView.png]]<br>
1563 In summary, we have implemented a simple TMF view using the SWTChart library. We made use of signals and requests to populate the view at the appropriate time and we formated the time stamps nicely. We also made sure that the time stamp format is updated when the preferences change.
1568 CTF is a format used to store traces. It is self defining, binary and made to be easy to write to.
1569 Before going further, the full specification of the CTF file format can be found at http://www.efficios.com/ .
1571 For the purpose of the reader some basic description will be given. A CTF trace typically is made of several files all in the same folder.
1573 These files can be split into two types :
1578 The metadata is either raw text or packetized text. It is tsdl encoded. it contains a description of the type of data in the event streams. It can grow over time if new events are added to a trace but it will never overwrite what is already there.
1580 === Event Streams ===
1581 The event streams are a file per stream per cpu. These streams are binary and packet based. The streams store events and event information (ie lost events) The event data is stored in headers and field payloads.
1583 So if you have two streams (channels) "channel1" and "channel2" and 4 cores, you will have the following files in your trace directory: "channel1_0" , "channel1_1" , "channel1_2" , "channel1_3" , "channel2_0" , "channel2_1" , "channel2_2" & "channel2_3"
1585 == Reading a trace ==
1586 In order to read a CTF trace, two steps must be done.
1587 * The metadata must be read to know how to read the events.
1588 * the events must be read.
1590 The metadata is a written in a subset of the C language called TSDL. To read it, first it is depacketized (if it is not in plain text) then the raw text is parsed by an antlr grammer. The parsing is done in two phases. There is a lexer (CTFLexer.g) which separated the metatdata text into tokens. The tokens are then pattern matched using the parser (CTFParser.g) to form an AST. This AST is walked through using "IOStructGen.java" to populate streams and traces in trace parent object.
1592 When the metadata is loaded and read, the trace object will be populated with 3 items:
1593 * the event definitions available per stream: a definition is a description of the datatype.
1594 * the event declarations available per stream: this will save declaration creation on a per event basis. They will all be created in advance, just not populated.
1595 * the beginning of a packet index.
1597 Now all the trace readers for the event streams have everything they need to read a trace. They will each point to one file, and read the file from packet to packet. Everytime the trace reader changes packet, the index is updated with the new packet's information. The readers are in a priority queue and sorted by timestamp. This ensures that the events are read in a sequential order. They are also sorted by file name so that in the eventuality that two events occur at the same time, they stay in the same order.
1599 == Seeking in a trace ==
1600 The reason for maintaining an index is to speed up seeks. In the case that a user wishes to seek to a certain timestamp, they just have to find the index entry that contains the timestamp, and go there to iterate in that packet until the proper event is found. this will reduce the searches time by an order of 8000 for a 256k paket size (kernel default).
1602 == Interfacing to TMF ==
1603 The trace can be read easily now but the data is still awkward to extract.
1606 A location in a given trace, it is currently the timestamp of a trace and the index of the event. The index shows for a given timestamp if it is the first second or nth element.
1609 The CtfTmfTrace is a wrapper for the standard CTF trace that allows it to perform the following actions:
1610 * '''initTrace()''' create a trace
1611 * '''validateTrace()''' is the trace a CTF trace?
1612 * '''getLocationRatio()''' how far in the trace is my location?
1613 * '''seekEvent()''' sets the cursor to a certain point in a trace.
1614 * '''readNextEvent()''' reads the next event and then advances the cursor
1615 * '''getTraceProperties()''' gets the 'env' structures of the metadata
1618 The CtfIterator is a wrapper to the CTF file reader. It behaves like an iterator on a trace. However, it contains a file pointer and thus cannot be duplicated too often or the system will run out of file handles. To alleviate the situation, a pool of iterators is created at the very beginning and stored in the CtfTmfTrace. They can be retried by calling the GetIterator() method.
1620 === CtfIteratorManager ===
1621 Since each CtfIterator will have a file reader, the OS will run out of handles if too many iterators are spawned. The solution is to use the iterator manager. This will allow the user to get an iterator. If there is a context at the requested position, the manager will return that one, if not, a context will be selected at random and set to the correct location. Using random replacement minimizes contention as it will settle quickly at a new balance point.
1623 === CtfTmfContext ===
1624 The CtfTmfContext implements the ITmfContext type. It is the CTF equivalent of TmfContext. It has a CtfLocation and points to an iterator in the CtfTmfTrace iterator pool as well as the parent trace. it is made to be cloned easily and not affect system resources much. Contexts behave much like C file pointers (FILE*) but they can be copied until one runs out of RAM.
1626 === CtfTmfTimestamp ===
1627 The CtfTmfTimestamp take a CTF time (normally a long int) and outputs the time formats it as a TmfTimestamp, allowing it to be compared to other timestamps. The time is stored with the UTC offset already applied. It also features a simple toString() function that allows it to output the time in more Human readable ways: "yyyy/mm/dd/hh:mm:ss.nnnnnnnnn ns" for example. An additional feature is the getDelta() function that allows two timestamps to be substracted, showing the time difference between A and B.
1630 The CtfTmfEvent is an ITmfEvent that is used to wrap event declarations and event definitions from the CTF side into easier to read and parse chunks of information. It is a final class with final fields made to be newed very often without incurring performance costs. Most of the information is already available. It should be noted that one type of event can appear called "lost event" these are synthetic events that do not exist in the trace. They will not appear in other trace readers such as babeltrace.
1633 There are other helper files that format given events for views, they are simpler and the architecture does not depend on them.
1636 For the moment live trace reading is not supported, there are no sources of traces to test on.