tmf: Move plugins to the Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / uml2sd / loader / TmfUml2SDSyncLoader.java
1 /**********************************************************************
2 * Copyright (c) 2011, 2013 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Bernd Hufmann - Initial API and implementation
11 **********************************************************************/
12
13 package org.eclipse.linuxtools.tmf.ui.views.uml2sd.loader;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.concurrent.CopyOnWriteArrayList;
20 import java.util.concurrent.locks.ReentrantLock;
21
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.core.runtime.jobs.Job;
26 import org.eclipse.jface.viewers.ISelection;
27 import org.eclipse.jface.viewers.StructuredSelection;
28 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
29 import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
30 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
31 import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
32 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
33 import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
34 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
35 import org.eclipse.linuxtools.tmf.core.signal.TmfSignal;
36 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
37 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
38 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
39 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
40 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
41 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
42 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
43 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
44 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
45 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
46 import org.eclipse.linuxtools.tmf.core.uml2sd.ITmfSyncSequenceDiagramEvent;
47 import org.eclipse.linuxtools.tmf.core.uml2sd.TmfSyncSequenceDiagramEvent;
48 import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
49 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDView;
50 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Frame;
51 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode;
52 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline;
53 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.dialogs.Criteria;
54 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.dialogs.FilterCriteria;
55 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.dialogs.FilterListDialog;
56 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.handlers.provider.ISDAdvancedPagingProvider;
57 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.handlers.provider.ISDFilterProvider;
58 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.handlers.provider.ISDFindProvider;
59 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.handlers.provider.ISDGraphNodeSupporter;
60 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.load.IUml2SDLoader;
61 import org.eclipse.swt.widgets.Display;
62 import org.eclipse.ui.IEditorPart;
63 import org.eclipse.ui.ISelectionListener;
64 import org.eclipse.ui.IWorkbenchPart;
65 import org.eclipse.ui.IWorkbenchWindow;
66 import org.eclipse.ui.PlatformUI;
67 import org.eclipse.ui.progress.IProgressConstants;
68
69 /**
70 * <p>
71 * This class is a reference implementation of the
72 * <code>org.eclipse.linuxtools.tmf.ui.Uml2SDLoader</code> extension point. It
73 * provides a Sequence Diagram loader for a user space trace with specific trace
74 * content for sending and receiving signals between components. I also includes
75 * a default implementation for the <code>ITmfEvent</code> parsing.
76 * </p>
77 *
78 * The class <code>TmfUml2SDSyncLoader</code> analyzes events from type
79 * <code>ITmfEvent</code> and creates events type
80 * <code>ITmfSyncSequenceDiagramEvent</code> if the <code>ITmfEvent</code>
81 * contains all relevant information. The analysis checks that the event type
82 * strings contains either string SEND or RECEIVE. If event type matches these
83 * key words, the analyzer will look for strings sender, receiver and signal in
84 * the event fields of type <code>ITmfEventField</code>. If all the data is
85 * found a sequence diagram event from can be created. Note that Sync Messages
86 * are assumed, which means start and end time are the same. <br>
87 * <br>
88 * The parsing of the <code>ITmfEvent</code> is done in the method
89 * <code>getSequnceDiagramEvent()</code> of class
90 * <code>TmfUml2SDSyncLoader</code>. By extending the class
91 * <code>TmfUml2SDSyncLoader</code> and overwriting
92 * <code>getSequnceDiagramEvent()</code> a customized parsing algorithm can be
93 * implemented.<br>
94 * <br>
95 * Note that combined traces of multiple components, that contain the trace
96 * information about the same interactions are not supported in the class
97 * <code>TmfUml2SDSyncLoader</code>.
98 *
99 * @version 1.0
100 * @author Bernd Hufmann
101 */
102 public class TmfUml2SDSyncLoader extends TmfComponent implements IUml2SDLoader, ISDFindProvider, ISDFilterProvider, ISDAdvancedPagingProvider, ISelectionListener {
103
104 // ------------------------------------------------------------------------
105 // Constants
106 // ------------------------------------------------------------------------
107
108 /**
109 * Default title name.
110 */
111 protected static final String TITLE = Messages.TmfUml2SDSyncLoader_ViewName;
112
113 /**
114 * Maximum number of messages per page.
115 */
116 protected static final int MAX_NUM_OF_MSG = 10000;
117
118 private static final int INDEXING_THREAD_SLEEP_VALUE = 100;
119
120 // ------------------------------------------------------------------------
121 // Attributes
122 // ------------------------------------------------------------------------
123
124 // Experiment attributes
125 /**
126 * The TMF trace reference.
127 * @since 2.0
128 */
129 protected ITmfTrace fTrace = null;
130 /**
131 * The current indexing event request.
132 */
133 protected ITmfEventRequest fIndexRequest = null;
134 /**
135 * The current request to fill a page.
136 */
137 protected ITmfEventRequest fPageRequest = null;
138 /**
139 * Flag whether the time range signal was sent by this loader class or not
140 */
141 protected volatile boolean fIsSignalSent = false;
142
143 // The view and event attributes
144 /**
145 * The sequence diagram view reference.
146 */
147 protected SDView fView = null;
148 /**
149 * The current sequence diagram frame reference.
150 */
151 protected Frame fFrame = null;
152 /**
153 * The list of sequence diagram events of current page.
154 */
155 protected List<ITmfSyncSequenceDiagramEvent> fEvents = new ArrayList<>();
156
157 // Checkpoint and page attributes
158 /**
159 * The checkpoints of the whole sequence diagram trace (i.e. start time stamp of each page)
160 */
161 protected List<TmfTimeRange> fCheckPoints = new ArrayList<>(MAX_NUM_OF_MSG);
162 /**
163 * The current page displayed.
164 */
165 protected volatile int fCurrentPage = 0;
166 /**
167 * The current time selected.
168 */
169 protected ITmfTimestamp fCurrentTime = null;
170 /**
171 * Flag to specify that selection of message is done by selection or by signal.
172 */
173 protected volatile boolean fIsSelect = false;
174
175 // Search attributes
176 /**
177 * The job for searching across pages.
178 */
179 protected SearchJob fFindJob = null;
180 /**
181 * List of found nodes within a page.
182 */
183 protected List<GraphNode> fFindResults = new ArrayList<>();
184 /**
185 * The current find criteria reference
186 */
187 protected Criteria fFindCriteria = null;
188 /**
189 * The current find index within the list of found nodes (<code>fFindeResults</code> within a page.
190 */
191 protected volatile int fCurrentFindIndex = 0;
192
193 // Filter attributes
194 /**
195 * The list of active filters.
196 */
197 protected List<FilterCriteria> fFilterCriteria = null;
198
199 // Thread synchronization
200 /**
201 * The synchronization lock.
202 */
203 protected ReentrantLock fLock = new ReentrantLock();
204
205 // ------------------------------------------------------------------------
206 // Constructors
207 // ------------------------------------------------------------------------
208 /**
209 * Default constructor
210 */
211 public TmfUml2SDSyncLoader() {
212 super(TITLE);
213 }
214
215 /**
216 * Constructor
217 *
218 * @param name Name of loader
219 */
220 public TmfUml2SDSyncLoader(String name) {
221 super(name);
222 }
223
224 // ------------------------------------------------------------------------
225 // Operations
226 // ------------------------------------------------------------------------
227
228 /**
229 * Returns the current time if available else null.
230 *
231 * @return the current time if available else null
232 * @since 2.0
233 */
234 public ITmfTimestamp getCurrentTime() {
235 fLock.lock();
236 try {
237 if (fCurrentTime != null) {
238 return fCurrentTime;
239 }
240 return null;
241 } finally {
242 fLock.unlock();
243 }
244 }
245
246 /**
247 * Waits for the page request to be completed
248 */
249 public void waitForCompletion() {
250 fLock.lock();
251 ITmfEventRequest request = fPageRequest;
252 fLock.unlock();
253 if (request != null) {
254 try {
255 request.waitForCompletion();
256 } catch (InterruptedException e) {
257 // ignore
258 }
259 }
260 }
261
262 /**
263 * Handler for the trace opened signal.
264 * @param signal The trace opened signal
265 * @since 2.0
266 */
267 @TmfSignalHandler
268 public void traceOpened(TmfTraceOpenedSignal signal) {
269 fTrace = signal.getTrace();
270 loadTrace();
271 }
272
273
274 /**
275 * Signal handler for the trace selected signal.
276 *
277 * Spawns a request to index the trace (checkpoints creation) as well as it fills
278 * the first page.
279 *
280 * @param signal The trace selected signal
281 * @since 2.0
282 */
283 @TmfSignalHandler
284 public void traceSelected(TmfTraceSelectedSignal signal) {
285 // Update the trace reference
286 ITmfTrace trace = signal.getTrace();
287 if (!trace.equals(fTrace)) {
288 fTrace = trace;
289 }
290 loadTrace();
291 }
292
293 /**
294 * Method for loading the current selected trace into the view.
295 * Sub-class need to override this method to add the view specific implementation.
296 * @since 2.0
297 */
298 protected void loadTrace() {
299 ITmfEventRequest indexRequest = null;
300 fLock.lock();
301
302 try {
303 final Job job = new IndexingJob("Indexing " + getName() + "..."); //$NON-NLS-1$ //$NON-NLS-2$
304 job.setUser(false);
305 job.schedule();
306
307 indexRequest = fIndexRequest;
308
309 cancelOngoingRequests();
310
311 TmfTimeRange window = TmfTimeRange.ETERNITY;
312
313 fIndexRequest = new TmfEventRequest(ITmfEvent.class, window, 0,
314 ITmfEventRequest.ALL_DATA, ITmfEventRequest.ExecutionType.BACKGROUND) {
315
316 private ITmfTimestamp fFirstTime = null;
317 private ITmfTimestamp fLastTime = null;
318 private int fNbSeqEvents = 0;
319 private final List<ITmfSyncSequenceDiagramEvent> fSdEvents = new ArrayList<>(MAX_NUM_OF_MSG);
320
321 @Override
322 public void handleData(ITmfEvent event) {
323 super.handleData(event);
324
325 ITmfSyncSequenceDiagramEvent sdEvent = getSequenceDiagramEvent(event);
326
327 if (sdEvent != null) {
328 ++fNbSeqEvents;
329
330 if (fFirstTime == null) {
331 fFirstTime = event.getTimestamp();
332 }
333
334 fLastTime = event.getTimestamp();
335
336 if ((fNbSeqEvents % MAX_NUM_OF_MSG) == 0) {
337 fLock.lock();
338 try {
339 fCheckPoints.add(new TmfTimeRange(fFirstTime, fLastTime));
340 if (fView != null) {
341 fView.updateCoolBar();
342 }
343 } finally {
344 fLock.unlock();
345 }
346 fFirstTime = null;
347
348 }
349
350 if (fNbSeqEvents > MAX_NUM_OF_MSG) {
351 // page is full
352 return;
353 }
354
355 fSdEvents.add(sdEvent);
356
357 if (fNbSeqEvents == MAX_NUM_OF_MSG) {
358 fillCurrentPage(fSdEvents);
359 }
360 }
361 }
362
363 @Override
364 public void handleSuccess() {
365 if ((fFirstTime != null) && (fLastTime != null)) {
366
367 fLock.lock();
368 try {
369 fCheckPoints.add(new TmfTimeRange(fFirstTime, fLastTime));
370 if (fView != null) {
371 fView.updateCoolBar();
372 }
373 } finally {
374 fLock.unlock();
375 }
376 }
377
378 if (fNbSeqEvents <= MAX_NUM_OF_MSG) {
379 fillCurrentPage(fSdEvents);
380 }
381
382 super.handleSuccess();
383 }
384
385 @Override
386 public void handleCompleted() {
387 if (fEvents.isEmpty()) {
388 fFrame = new Frame();
389 // make sure that view is not null when setting frame
390 SDView sdView;
391 fLock.lock();
392 try {
393 sdView = fView;
394 } finally {
395 fLock.unlock();
396 }
397 if (sdView != null) {
398 sdView.setFrameSync(fFrame);
399 }
400 }
401 super.handleCompleted();
402 job.cancel();
403 }
404 };
405
406 } finally {
407 fLock.unlock();
408 }
409 if (indexRequest != null && !indexRequest.isCompleted()) {
410 indexRequest.cancel();
411 }
412 resetLoader();
413 fTrace.sendRequest(fIndexRequest);
414 }
415
416 /**
417 * Signal handler for the trace closed signal.
418 *
419 * @param signal The trace closed signal
420 * @since 2.0
421 */
422 @TmfSignalHandler
423 public void traceClosed(TmfTraceClosedSignal signal) {
424 if (signal.getTrace() != fTrace) {
425 return;
426 }
427 ITmfEventRequest indexRequest = null;
428 fLock.lock();
429 try {
430 indexRequest = fIndexRequest;
431 fIndexRequest = null;
432
433 cancelOngoingRequests();
434
435 if (fFilterCriteria != null) {
436 fFilterCriteria.clear();
437 }
438
439 FilterListDialog.deactivateSavedGlobalFilters();
440 } finally {
441 fTrace = null;
442 fLock.unlock();
443 }
444 if (indexRequest != null && !indexRequest.isCompleted()) {
445 indexRequest.cancel();
446 }
447
448 resetLoader();
449 }
450
451 /**
452 * Moves to the page that contains the time provided by the signal. The messages will be selected
453 * if the provided time is the time of a message.
454 *
455 * @param signal The Time synch signal.
456 */
457 @TmfSignalHandler
458 public void synchToTime(TmfTimeSynchSignal signal) {
459 fLock.lock();
460 try {
461 if ((signal.getSource() != this) && (fFrame != null) && (fCheckPoints.size() > 0)) {
462 fCurrentTime = signal.getBeginTime();
463 fIsSelect = true;
464 moveToMessage();
465 }
466 } finally {
467 fLock.unlock();
468 }
469 }
470
471 /**
472 * Moves to the page that contains the current time provided by signal.
473 * No message will be selected however the focus will be set to the message
474 * if the provided time is the time of a message.
475 *
476 * @param signal The time range sync signal
477 */
478 @TmfSignalHandler
479 public void synchToTimeRange(TmfRangeSynchSignal signal) {
480 fLock.lock();
481 try {
482 if ((signal.getSource() != this) && (fFrame != null) && !fIsSignalSent && (fCheckPoints.size() > 0)) {
483 TmfTimeRange newTimeRange = signal.getCurrentRange();
484
485 fIsSelect = false;
486 fCurrentTime = newTimeRange.getStartTime();
487
488 moveToMessage();
489 }
490 } finally {
491 fLock.unlock();
492 }
493
494 }
495
496 @Override
497 public void setViewer(SDView viewer) {
498
499 fLock.lock();
500 try {
501 fView = viewer;
502 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().addPostSelectionListener(this);
503 fView.setSDFindProvider(this);
504 fView.setSDPagingProvider(this);
505 fView.setSDFilterProvider(this);
506
507 resetLoader();
508 IEditorPart editor = fView.getSite().getPage().getActiveEditor();
509 if (editor instanceof ITmfTraceEditor) {
510 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
511 if (trace != null) {
512 traceSelected(new TmfTraceSelectedSignal(this, trace));
513 }
514 }
515 } finally {
516 fLock.unlock();
517 }
518 }
519
520 @Override
521 public String getTitleString() {
522 return getName();
523 }
524
525 @Override
526 public void dispose() {
527 super.dispose();
528 ITmfEventRequest indexRequest = null;
529 fLock.lock();
530 try {
531 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
532 // During Eclipse shutdown the active workbench window is null
533 if (window != null) {
534 window.getSelectionService().removePostSelectionListener(this);
535 }
536
537 indexRequest = fIndexRequest;
538 fIndexRequest = null;
539 cancelOngoingRequests();
540
541 fView.setSDFindProvider(null);
542 fView.setSDPagingProvider(null);
543 fView.setSDFilterProvider(null);
544 fView = null;
545 } finally {
546 fLock.unlock();
547 }
548 if (indexRequest != null && !indexRequest.isCompleted()) {
549 indexRequest.cancel();
550 }
551 }
552
553 @Override
554 public boolean isNodeSupported(int nodeType) {
555 switch (nodeType) {
556 case ISDGraphNodeSupporter.LIFELINE:
557 case ISDGraphNodeSupporter.SYNCMESSAGE:
558 return true;
559
560 default:
561 break;
562 }
563 return false;
564 }
565
566 @Override
567 public String getNodeName(int nodeType, String loaderClassName) {
568 switch (nodeType) {
569 case ISDGraphNodeSupporter.LIFELINE:
570 return Messages.TmfUml2SDSyncLoader_CategoryLifeline;
571 case ISDGraphNodeSupporter.SYNCMESSAGE:
572 return Messages.TmfUml2SDSyncLoader_CategoryMessage;
573 default:
574 break;
575 }
576 return ""; //$NON-NLS-1$
577 }
578
579 @Override
580 public void selectionChanged(IWorkbenchPart part, ISelection selection) {
581 ISelection sel = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
582 if ((sel != null) && (sel instanceof StructuredSelection)) {
583 StructuredSelection stSel = (StructuredSelection) sel;
584 if (stSel.getFirstElement() instanceof TmfSyncMessage) {
585 TmfSyncMessage syncMsg = ((TmfSyncMessage) stSel.getFirstElement());
586 broadcast(new TmfTimeSynchSignal(this, syncMsg.getStartTime()));
587 }
588 }
589 }
590
591 @Override
592 public boolean find(Criteria toSearch) {
593 fLock.lock();
594 try {
595 if (fFrame == null) {
596 return false;
597 }
598
599 if ((fFindResults == null) || (fFindCriteria == null) || !fFindCriteria.compareTo(toSearch)) {
600 fFindResults = new CopyOnWriteArrayList<>();
601 fFindCriteria = toSearch;
602 if (fFindCriteria.isLifeLineSelected()) {
603 for (int i = 0; i < fFrame.lifeLinesCount(); i++) {
604 if (fFindCriteria.matches(fFrame.getLifeline(i).getName())) {
605 fFindResults.add(fFrame.getLifeline(i));
606 }
607 }
608 }
609
610 ArrayList<GraphNode> msgs = new ArrayList<>();
611 if (fFindCriteria.isSyncMessageSelected()) {
612 for (int i = 0; i < fFrame.syncMessageCount(); i++) {
613 if (fFindCriteria.matches(fFrame.getSyncMessage(i).getName())) {
614 msgs.add(fFrame.getSyncMessage(i));
615 }
616 }
617 }
618
619 if (!msgs.isEmpty()) {
620 fFindResults.addAll(msgs);
621 }
622
623 List<GraphNode> selection = fView.getSDWidget().getSelection();
624 if ((selection != null) && (selection.size() == 1)) {
625 fCurrentFindIndex = fFindResults.indexOf(selection.get(0)) + 1;
626 } else {
627 fCurrentFindIndex = 0;
628 }
629 } else {
630 fCurrentFindIndex++;
631 }
632
633 if (fFindResults.size() > fCurrentFindIndex) {
634 GraphNode current = fFindResults.get(fCurrentFindIndex);
635 fView.getSDWidget().moveTo(current);
636 return true;
637 }
638 fFindResults = null;
639 fCurrentFindIndex =0;
640 return findInNextPages(fFindCriteria); // search in other page
641 } finally {
642 fLock.unlock();
643 }
644 }
645
646 @Override
647 public void cancel() {
648 cancelOngoingRequests();
649 }
650
651 @Override
652 public boolean filter(List<FilterCriteria> filters) {
653 fLock.lock();
654 try {
655 cancelOngoingRequests();
656
657 if (filters == null) {
658 fFilterCriteria = new ArrayList<>();
659 } else {
660 List<FilterCriteria> list = filters;
661 fFilterCriteria = new ArrayList<>(list);
662 }
663
664 fillCurrentPage(fEvents);
665
666 } finally {
667 fLock.unlock();
668 }
669 return true;
670 }
671
672 @Override
673 public boolean hasNextPage() {
674 fLock.lock();
675 try {
676 int size = fCheckPoints.size();
677 if (size > 0) {
678 return fCurrentPage < (size - 1);
679 }
680 } finally {
681 fLock.unlock();
682 }
683 return false;
684 }
685
686 @Override
687 public boolean hasPrevPage() {
688 fLock.lock();
689 try {
690 return fCurrentPage > 0;
691 } finally {
692 fLock.unlock();
693 }
694 }
695
696 @Override
697 public void nextPage() {
698 fLock.lock();
699 try {
700 // Safety check
701 if (fCurrentPage >= (fCheckPoints.size() - 1)) {
702 return;
703 }
704
705 cancelOngoingRequests();
706 fCurrentTime = null;
707 fCurrentPage++;
708 moveToPage();
709 } finally {
710 fLock.unlock();
711 }
712 }
713
714 @Override
715 public void prevPage() {
716 fLock.lock();
717 try {
718 // Safety check
719 if (fCurrentPage <= 0) {
720 return;
721 }
722
723 cancelOngoingRequests();
724 fCurrentTime = null;
725 fCurrentPage--;
726 moveToPage();
727 } finally {
728 fLock.unlock();
729 }
730 }
731
732 @Override
733 public void firstPage() {
734 fLock.lock();
735 try {
736
737 cancelOngoingRequests();
738 fCurrentTime = null;
739 fCurrentPage = 0;
740 moveToPage();
741 } finally {
742 fLock.unlock();
743 }
744 }
745
746 @Override
747 public void lastPage() {
748 fLock.lock();
749 try {
750 cancelOngoingRequests();
751 fCurrentTime = null;
752 fCurrentPage = fCheckPoints.size() - 1;
753 moveToPage();
754 } finally {
755 fLock.unlock();
756 }
757 }
758
759 @Override
760 public int currentPage() {
761 fLock.lock();
762 try {
763 return fCurrentPage;
764 } finally {
765 fLock.unlock();
766 }
767 }
768
769 @Override
770 public int pagesCount() {
771 fLock.lock();
772 try {
773 return fCheckPoints.size();
774 } finally {
775 fLock.unlock();
776 }
777 }
778
779 @Override
780 public void pageNumberChanged(int pagenNumber) {
781 int localPageNumber = pagenNumber;
782
783 fLock.lock();
784 try {
785 cancelOngoingRequests();
786
787 if (localPageNumber < 0) {
788 localPageNumber = 0;
789 }
790 int size = fCheckPoints.size();
791 if (localPageNumber > (size - 1)) {
792 localPageNumber = size - 1;
793 }
794 fCurrentPage = localPageNumber;
795 moveToPage();
796 } finally {
797 fLock.unlock();
798 }
799 }
800
801 @Override
802 public void broadcast(TmfSignal signal) {
803 fIsSignalSent = true;
804 super.broadcast(signal);
805 fIsSignalSent = false;
806 }
807
808 /**
809 * Cancels any ongoing find operation
810 */
811 protected void cancelOngoingRequests() {
812 fLock.lock();
813 ITmfEventRequest pageRequest = null;
814 try {
815 // Cancel the search thread
816 if (fFindJob != null) {
817 fFindJob.cancel();
818 }
819
820 fFindResults = null;
821 fFindCriteria = null;
822 fCurrentFindIndex = 0;
823
824 pageRequest = fPageRequest;
825 fPageRequest = null;
826 } finally {
827 fLock.unlock();
828 }
829 if (pageRequest != null && !pageRequest.isCompleted()) {
830 pageRequest.cancel();
831 }
832 }
833
834 /**
835 * Resets loader attributes
836 */
837 protected void resetLoader() {
838 fLock.lock();
839 try {
840 fCurrentTime = null;
841 fEvents.clear();
842 fCheckPoints.clear();
843 fCurrentPage = 0;
844 fCurrentFindIndex = 0;
845 fFindCriteria = null;
846 fFindResults = null;
847 fView.setFrameSync(new Frame());
848 fFrame = null;
849 }
850 finally {
851 fLock.unlock();
852 }
853
854 }
855
856 /**
857 * Fills current page with sequence diagram content.
858 *
859 * @param events sequence diagram events
860 */
861 protected void fillCurrentPage(List<ITmfSyncSequenceDiagramEvent> events) {
862
863 fLock.lock();
864 try {
865 fEvents = new ArrayList<>(events);
866 if (fView != null && !events.isEmpty()) {
867 fView.toggleWaitCursorAsync(true);
868 }
869 } finally {
870 fLock.unlock();
871 }
872
873 final Frame frame = new Frame();
874
875 if (!events.isEmpty()) {
876 Map<String, Lifeline> nodeToLifelineMap = new HashMap<>();
877
878 frame.setName(Messages.TmfUml2SDSyncLoader_FrameName);
879
880 for (int i = 0; i < events.size(); i++) {
881
882 ITmfSyncSequenceDiagramEvent sdEvent = events.get(i);
883
884 if ((nodeToLifelineMap.get(sdEvent.getSender()) == null) && (!filterLifeLine(sdEvent.getSender()))) {
885 Lifeline lifeline = new Lifeline();
886 lifeline.setName(sdEvent.getSender());
887 nodeToLifelineMap.put(sdEvent.getSender(), lifeline);
888 frame.addLifeLine(lifeline);
889 }
890
891 if ((nodeToLifelineMap.get(sdEvent.getReceiver()) == null) && (!filterLifeLine(sdEvent.getReceiver()))) {
892 Lifeline lifeline = new Lifeline();
893 lifeline.setName(sdEvent.getReceiver());
894 nodeToLifelineMap.put(sdEvent.getReceiver(), lifeline);
895 frame.addLifeLine(lifeline);
896 }
897 }
898
899 int eventOccurence = 1;
900
901 for (int i = 0; i < events.size(); i++) {
902 ITmfSyncSequenceDiagramEvent sdEvent = events.get(i);
903
904 // Check message filter
905 if (filterMessage(sdEvent)) {
906 continue;
907 }
908
909 // Set the message sender and receiver
910 Lifeline startLifeline = nodeToLifelineMap.get(sdEvent.getSender());
911 Lifeline endLifeline = nodeToLifelineMap.get(sdEvent.getReceiver());
912
913 // Check if any of the lifelines were filtered
914 if ((startLifeline == null) || (endLifeline == null)) {
915 continue;
916 }
917
918 int tmp = Math.max(startLifeline.getEventOccurrence(), endLifeline.getEventOccurrence());
919 eventOccurence = Math.max(eventOccurence, tmp);
920
921 startLifeline.setCurrentEventOccurrence(eventOccurence);
922 endLifeline.setCurrentEventOccurrence(eventOccurence);
923
924 TmfSyncMessage message = new TmfSyncMessage(sdEvent, eventOccurence++);
925
926 message.setStartLifeline(startLifeline);
927 message.setEndLifeline(endLifeline);
928
929 message.setTime(sdEvent.getStartTime());
930
931 // add the message to the frame
932 frame.addMessage(message);
933
934 }
935 fLock.lock();
936 try {
937 if (!fView.getSDWidget().isDisposed()) {
938 fView.getSDWidget().getDisplay().asyncExec(new Runnable() {
939
940 @Override
941 public void run() {
942
943 fLock.lock();
944 try {
945 // check if view was disposed in the meanwhile
946 if ((fView != null) && (!fView.getSDWidget().isDisposed())) {
947 fFrame = frame;
948 fView.setFrame(fFrame);
949
950 if (fCurrentTime != null) {
951 moveToMessageInPage();
952 }
953
954 if (fFindCriteria != null) {
955 find(fFindCriteria);
956 }
957
958 fView.toggleWaitCursorAsync(false);
959 }
960 } finally {
961 fLock.unlock();
962 }
963
964 }
965 });
966 }
967 }
968 finally {
969 fLock.unlock();
970 }
971 }
972 }
973
974 /**
975 * Moves to a certain message defined by timestamp (across pages)
976 */
977 protected void moveToMessage() {
978 int page = 0;
979
980 fLock.lock();
981 try {
982 page = getPage(fCurrentTime);
983
984 if (page == fCurrentPage) {
985 moveToMessageInPage();
986 return;
987 }
988 fCurrentPage = page;
989 moveToPage(false);
990 } finally {
991 fLock.unlock();
992 }
993 }
994
995 /**
996 * Moves to a certain message defined by timestamp in current page
997 */
998 protected void moveToMessageInPage() {
999 fLock.lock();
1000 try {
1001 if (!fView.getSDWidget().isDisposed()) {
1002 // Check for GUI thread
1003 if(Display.getCurrent() != null) {
1004 // Already in GUI thread - execute directly
1005 TmfSyncMessage prevMessage = null;
1006 TmfSyncMessage syncMessage = null;
1007 boolean isExactTime = false;
1008 for (int i = 0; i < fFrame.syncMessageCount(); i++) {
1009 if (fFrame.getSyncMessage(i) instanceof TmfSyncMessage) {
1010 syncMessage = (TmfSyncMessage) fFrame.getSyncMessage(i);
1011 if (syncMessage.getStartTime().compareTo(fCurrentTime, false) == 0) {
1012 isExactTime = true;
1013 break;
1014 } else if ((syncMessage.getStartTime().compareTo(fCurrentTime, false) > 0) && (prevMessage != null)) {
1015 syncMessage = prevMessage;
1016 break;
1017 }
1018 prevMessage = syncMessage;
1019 }
1020 }
1021 if (fIsSelect && isExactTime) {
1022 fView.getSDWidget().moveTo(syncMessage);
1023 }
1024 else {
1025 fView.getSDWidget().ensureVisible(syncMessage);
1026 fView.getSDWidget().clearSelection();
1027 fView.getSDWidget().redraw();
1028 }
1029 }
1030 else {
1031 // Not in GUI thread - queue action in GUI thread.
1032 fView.getSDWidget().getDisplay().asyncExec(new Runnable() {
1033 @Override
1034 public void run() {
1035 moveToMessageInPage();
1036 }
1037 });
1038 }
1039 }
1040 }
1041 finally {
1042 fLock.unlock();
1043 }
1044 }
1045
1046 /**
1047 * Moves to a certain message defined by timestamp (across pages)
1048 */
1049 protected void moveToPage() {
1050 moveToPage(true);
1051 }
1052
1053 /**
1054 * Moves to a certain page.
1055 *
1056 * @param notifyAll true to broadcast time range signal to other signal handlers else false
1057 */
1058 protected void moveToPage(boolean notifyAll) {
1059
1060 TmfTimeRange window = null;
1061
1062 fLock.lock();
1063 try {
1064 // Safety check
1065 if (fCurrentPage > fCheckPoints.size()) {
1066 return;
1067 }
1068 window = fCheckPoints.get(fCurrentPage);
1069 } finally {
1070 fLock.unlock();
1071 }
1072
1073 if (window == null) {
1074 window = TmfTimeRange.ETERNITY;
1075 }
1076
1077 fPageRequest = new TmfEventRequest(ITmfEvent.class, window, 0,
1078 ITmfEventRequest.ALL_DATA, ITmfEventRequest.ExecutionType.FOREGROUND) {
1079 private final List<ITmfSyncSequenceDiagramEvent> fSdEvent = new ArrayList<>();
1080
1081 @Override
1082 public void handleData(ITmfEvent event) {
1083 super.handleData(event);
1084
1085 ITmfSyncSequenceDiagramEvent sdEvent = getSequenceDiagramEvent(event);
1086
1087 if (sdEvent != null) {
1088 fSdEvent.add(sdEvent);
1089 }
1090 }
1091
1092 @Override
1093 public void handleSuccess() {
1094 fillCurrentPage(fSdEvent);
1095 super.handleSuccess();
1096 }
1097
1098 };
1099
1100 fTrace.sendRequest(fPageRequest);
1101
1102 if (notifyAll) {
1103 TmfTimeRange timeRange = getSignalTimeRange(window.getStartTime());
1104 broadcast(new TmfRangeSynchSignal(this, timeRange));
1105 }
1106 }
1107
1108 /**
1109 * Gets page that contains timestamp
1110 *
1111 * @param time The timestamp
1112 * @return page that contains the time
1113 * @since 2.0
1114 */
1115 protected int getPage(ITmfTimestamp time) {
1116 int page;
1117 int size;
1118 fLock.lock();
1119 try {
1120 size = fCheckPoints.size();
1121 for (page = 0; page < size; page++) {
1122 TmfTimeRange timeRange = fCheckPoints.get(page);
1123 if (timeRange.getEndTime().compareTo(time, false) >= 0) {
1124 break;
1125 }
1126 }
1127 if (page >= size) {
1128 page = size - 1;
1129 }
1130 return page;
1131 } finally {
1132 fLock.unlock();
1133 }
1134 }
1135
1136 /**
1137 * Background search in trace for expression in criteria.
1138 *
1139 * @param findCriteria The find criteria
1140 * @return true if background request was started else false
1141 */
1142 protected boolean findInNextPages(Criteria findCriteria) {
1143 fLock.lock();
1144 try {
1145 if (fFindJob != null) {
1146 return true;
1147 }
1148
1149 int nextPage = fCurrentPage + 1;
1150
1151 if ((nextPage) >= fCheckPoints.size()) {
1152 // we are at the end
1153 return false;
1154 }
1155
1156 TmfTimeRange window = new TmfTimeRange(fCheckPoints.get(nextPage).getStartTime(), fCheckPoints.get(fCheckPoints.size()-1).getEndTime());
1157 fFindJob = new SearchJob(findCriteria, window);
1158 fFindJob.schedule();
1159 fView.toggleWaitCursorAsync(true);
1160 } finally {
1161 fLock.unlock();
1162 }
1163 return true;
1164 }
1165
1166 /**
1167 * Gets time range for time range signal.
1168 *
1169 * @param startTime The start time of time range.
1170 * @return the time range
1171 * @since 2.0
1172 */
1173 protected TmfTimeRange getSignalTimeRange(ITmfTimestamp startTime) {
1174 fLock.lock();
1175 try {
1176 TmfTimeRange currentRange = TmfTraceManager.getInstance().getCurrentRange();
1177 long offset = fTrace == null ? 0 : currentRange.getEndTime().getDelta(currentRange.getStartTime()).normalize(0, startTime.getScale()).getValue();
1178 TmfTimestamp initialEndOfWindow = new TmfTimestamp(startTime.getValue() + offset, startTime.getScale(), startTime.getPrecision());
1179 return new TmfTimeRange(startTime, initialEndOfWindow);
1180 }
1181 finally {
1182 fLock.unlock();
1183 }
1184 }
1185
1186 /**
1187 * Checks if filter criteria matches the message name in given SD event.
1188 *
1189 * @param sdEvent The SD event to check
1190 * @return true if match else false.
1191 */
1192 protected boolean filterMessage(ITmfSyncSequenceDiagramEvent sdEvent) {
1193 fLock.lock();
1194 try {
1195 if (fFilterCriteria != null) {
1196 for(FilterCriteria criteria : fFilterCriteria) {
1197 if (criteria.isActive() && criteria.getCriteria().isSyncMessageSelected() && criteria.getCriteria().matches(sdEvent.getName())) {
1198 return true;
1199 }
1200 }
1201 }
1202 } finally {
1203 fLock.unlock();
1204 }
1205 return false;
1206 }
1207
1208 /**
1209 * Checks if filter criteria matches a lifeline name (sender or receiver) in given SD event.
1210 *
1211 * @param lifeline the message receiver
1212 * @return true if match else false.
1213 */
1214 protected boolean filterLifeLine(String lifeline) {
1215 fLock.lock();
1216 try {
1217 if (fFilterCriteria != null) {
1218 for(FilterCriteria criteria : fFilterCriteria) {
1219 if (criteria.isActive() && criteria.getCriteria().isLifeLineSelected() && criteria.getCriteria().matches(lifeline)) {
1220 return true;
1221 }
1222 }
1223 }
1224 } finally {
1225 fLock.unlock();
1226 }
1227 return false;
1228 }
1229
1230 /**
1231 * Job to search in trace for given time range.
1232 */
1233 protected class SearchJob extends Job {
1234
1235 /**
1236 * The search event request.
1237 */
1238 protected final SearchEventRequest fSearchRequest;
1239
1240 /**
1241 * Constructor
1242 *
1243 * @param findCriteria The search criteria
1244 * @param window Time range to search in
1245 * @since 2.0
1246 */
1247 public SearchJob(Criteria findCriteria, TmfTimeRange window) {
1248 super(Messages.TmfUml2SDSyncLoader_SearchJobDescrition);
1249 fSearchRequest = new SearchEventRequest(window, ITmfEventRequest.ALL_DATA,
1250 ITmfEventRequest.ExecutionType.FOREGROUND, findCriteria);
1251 }
1252
1253 @Override
1254 protected IStatus run(IProgressMonitor monitor) {
1255 fSearchRequest.setMonitor(monitor);
1256
1257 fTrace.sendRequest(fSearchRequest);
1258
1259 try {
1260 fSearchRequest.waitForCompletion();
1261 } catch (InterruptedException e) {
1262 Activator.getDefault().logError("Search request interrupted!", e); //$NON-NLS-1$
1263 }
1264
1265 IStatus status = Status.OK_STATUS;
1266 if (fSearchRequest.isFound() && (fSearchRequest.getFoundTime() != null)) {
1267 fCurrentTime = fSearchRequest.getFoundTime();
1268
1269 // Avoid double-selection. Selection will be done when calling find(criteria)
1270 // after moving to relevant page
1271 fIsSelect = false;
1272 if (!fView.getSDWidget().isDisposed()) {
1273 fView.getSDWidget().getDisplay().asyncExec(new Runnable() {
1274
1275 @Override
1276 public void run() {
1277 moveToMessage();
1278 }
1279 });
1280 }
1281 }
1282 else {
1283 if (monitor.isCanceled()) {
1284 status = Status.CANCEL_STATUS;
1285 }
1286 else {
1287 // String was not found
1288 status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, Messages.TmfUml2SDSyncLoader_SearchNotFound);
1289 }
1290 setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
1291 }
1292 monitor.done();
1293
1294 fLock.lock();
1295 try {
1296 fView.toggleWaitCursorAsync(false);
1297 fFindJob = null;
1298 } finally {
1299 fLock.unlock();
1300 }
1301
1302 return status;
1303 }
1304
1305 @Override
1306 protected void canceling() {
1307 fSearchRequest.cancel();
1308 fLock.lock();
1309 try {
1310 fFindJob = null;
1311 } finally {
1312 fLock.unlock();
1313 }
1314 }
1315 }
1316
1317 /**
1318 * TMF event request for searching within trace.
1319 */
1320 protected class SearchEventRequest extends TmfEventRequest {
1321
1322 /**
1323 * The find criteria.
1324 */
1325 private final Criteria fCriteria;
1326 /**
1327 * A progress monitor
1328 */
1329 private IProgressMonitor fMonitor;
1330 /**
1331 * Flag to indicate that node was found according the criteria .
1332 */
1333 private boolean fIsFound = false;
1334 /**
1335 * Time stamp of found item.
1336 */
1337 private ITmfTimestamp fFoundTime = null;
1338
1339 /**
1340 * Constructor
1341 * @param range @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#TmfEventRequest(...)
1342 * @param nbRequested @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#handleData(...)
1343 * @param execType @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#handleData(...)
1344 * @param criteria The search criteria
1345 */
1346 public SearchEventRequest(TmfTimeRange range, int nbRequested, ExecutionType execType, Criteria criteria) {
1347 this(range, nbRequested, execType, criteria, null);
1348 }
1349
1350 /**
1351 * Constructor
1352 * @param range @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#TmfEventRequest(...)
1353 * @param nbRequested @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#TmfEventRequest(...)
1354 * @param execType @see org.eclipse.linuxtools.tmf.request.TmfEventRequest#TmfEventRequest(...)
1355 * @param criteria The search criteria
1356 * @param monitor progress monitor
1357 */
1358 public SearchEventRequest(TmfTimeRange range, int nbRequested, ExecutionType execType, Criteria criteria, IProgressMonitor monitor) {
1359 super(ITmfEvent.class, range, 0, nbRequested, execType);
1360 fCriteria = new Criteria(criteria);
1361 fMonitor = monitor;
1362 }
1363
1364 @Override
1365 public void handleData(ITmfEvent event) {
1366 super.handleData(event);
1367
1368 if ((fMonitor!= null) && fMonitor.isCanceled()) {
1369 super.cancel();
1370 return;
1371 }
1372
1373 ITmfSyncSequenceDiagramEvent sdEvent = getSequenceDiagramEvent(event);
1374
1375 if (sdEvent != null) {
1376
1377 if (fCriteria.isLifeLineSelected()) {
1378 if (fCriteria.matches(sdEvent.getSender())) {
1379 fFoundTime = event.getTimestamp();
1380 fIsFound = true;
1381 super.cancel();
1382 }
1383
1384 if (fCriteria.matches(sdEvent.getReceiver())) {
1385 fFoundTime = event.getTimestamp();
1386 fIsFound = true;
1387 super.cancel();
1388 }
1389 }
1390
1391 if (fCriteria.isSyncMessageSelected() && fCriteria.matches(sdEvent.getName())) {
1392 fFoundTime = event.getTimestamp();
1393 fIsFound = true;
1394 super.cancel();
1395 }
1396 }
1397 }
1398
1399 /**
1400 * Set progress monitor.
1401 *
1402 * @param monitor The monitor to assign
1403 */
1404 public void setMonitor(IProgressMonitor monitor) {
1405 fMonitor = monitor;
1406 }
1407
1408 /**
1409 * Check if find criteria was met.
1410 *
1411 * @return true if find criteria was met.
1412 */
1413 public boolean isFound() {
1414 return fIsFound;
1415 }
1416
1417 /**
1418 * Returns timestamp of found time.
1419 *
1420 * @return timestamp of found time.
1421 * @since 2.0
1422 */
1423 public ITmfTimestamp getFoundTime() {
1424 return fFoundTime;
1425 }
1426 }
1427
1428 /**
1429 * Job class to provide progress monitor feedback.
1430 *
1431 * @version 1.0
1432 * @author Bernd Hufmann
1433 *
1434 */
1435 protected static class IndexingJob extends Job {
1436
1437 /**
1438 * @param name The job name
1439 */
1440 public IndexingJob(String name) {
1441 super(name);
1442 }
1443
1444 @Override
1445 protected IStatus run(IProgressMonitor monitor) {
1446 while (!monitor.isCanceled()) {
1447 try {
1448 Thread.sleep(INDEXING_THREAD_SLEEP_VALUE);
1449 } catch (InterruptedException e) {
1450 return Status.OK_STATUS;
1451 }
1452 }
1453 monitor.done();
1454 return Status.OK_STATUS;
1455 }
1456 }
1457
1458
1459 /**
1460 * Returns sequence diagram event if details in given event are available else null.
1461 *
1462 * @param tmfEvent Event to parse for sequence diagram event details
1463 * @return sequence diagram event if details are available else null
1464 * @since 2.0
1465 */
1466 protected ITmfSyncSequenceDiagramEvent getSequenceDiagramEvent(ITmfEvent tmfEvent){
1467 //type = .*RECEIVE.* or .*SEND.*
1468 //content = sender:<sender name>:receiver:<receiver name>,signal:<signal name>
1469 String eventType = tmfEvent.getType().toString();
1470 if (eventType.contains(Messages.TmfUml2SDSyncLoader_EventTypeSend) || eventType.contains(Messages.TmfUml2SDSyncLoader_EventTypeReceive)) {
1471 Object sender = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldSender);
1472 Object receiver = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldReceiver);
1473 Object name = tmfEvent.getContent().getField(Messages.TmfUml2SDSyncLoader_FieldSignal);
1474 if ((sender instanceof ITmfEventField) && (receiver instanceof ITmfEventField) && (name instanceof ITmfEventField)) {
1475 ITmfSyncSequenceDiagramEvent sdEvent = new TmfSyncSequenceDiagramEvent(tmfEvent,
1476 ((ITmfEventField) sender).getValue().toString(),
1477 ((ITmfEventField) receiver).getValue().toString(),
1478 ((ITmfEventField) name).getValue().toString());
1479
1480 return sdEvent;
1481 }
1482 }
1483 return null;
1484 }
1485 }
This page took 0.064647 seconds and 5 git commands to generate.