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