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