Monster merge from the integration branch. Still some problems left and JUnits failing.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / common / AbsTimeUpdateView.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 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 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12 package org.eclipse.linuxtools.lttng.ui.views.common;
13
14 import java.util.Arrays;
15
16 import org.eclipse.linuxtools.lttng.control.LttngCoreProviderFactory;
17 import org.eclipse.linuxtools.lttng.control.LttngSyntheticEventProvider;
18 import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent;
19 import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd;
20 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
21 import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest;
22 import org.eclipse.linuxtools.lttng.request.IRequestStatusListener;
23 import org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest;
24 import org.eclipse.linuxtools.lttng.request.RequestCompletedSignal;
25 import org.eclipse.linuxtools.lttng.request.RequestStartedSignal;
26 import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
27 import org.eclipse.linuxtools.lttng.ui.TraceDebug;
28 import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
29 import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory;
30 import org.eclipse.linuxtools.tmf.event.TmfEvent;
31 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
32 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
33 import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
34 import org.eclipse.linuxtools.tmf.request.TmfDataRequest;
35 import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
36 import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
37 import org.eclipse.linuxtools.tmf.signal.TmfSignalManager;
38 import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
39 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer;
40 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
41 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent;
42 import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
43 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
44 import org.eclipse.swt.widgets.Display;
45
46 /**
47 * <p>
48 * Abstract class used as a base for views handling specific time range data
49 * requests
50 * </p>
51 * <p>
52 * The class handles a single element queue of data requests, i.e. request can
53 * be triggered from different sources e.g. opening a file as well as a new
54 * selected time window
55 * </p>
56 *
57 * @author alvaro
58 *
59 */
60 public abstract class AbsTimeUpdateView extends TmfView implements
61 IRequestStatusListener {
62
63 // ========================================================================
64 // Data
65 // ========================================================================
66 /**
67 * One second in nanoseconds
68 */
69 private static final long INITIAL_WINDOW_OFFSET = 1000000000L; /*
70 * 1 sec //
71 * in ns //
72 */
73 // private static final long INITIAL_WINDOW_OFFSET = 100000000L; /* 100 ms
74 // in ns */
75 /**
76 * Number of events before a GUI refresh
77 */
78 private static final Long INPUT_CHANGED_REFRESH = 3000L;
79 private static final long DEFAULT_OFFSET = 0L;
80 private static final int DEFAULT_CHUNK = 1;
81
82 protected boolean synch = true; // time synchronisation, used to be an
83 // option
84 protected ITimeAnalysisViewer tsfviewer = null;
85
86 // ========================================================================
87 // Constructor
88 // ========================================================================
89 public AbsTimeUpdateView(String viewID) {
90 super(viewID);
91 // freqState = UiCommonFactory.getQueue(this);
92 }
93
94 // ========================================================================
95 // Methods
96 // ========================================================================
97 /*
98 * (non-Javadoc)
99 *
100 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
101 * processingStarted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
102 */
103 @TmfSignalHandler
104 public synchronized void processingStarted(RequestStartedSignal signal) {
105 LttngSyntEventRequest request = signal.getRequest();
106 if (request != null) {
107 // update queue with the id of the current request.
108 // freqState.requestStarted(request);
109
110 // if there was no new request then this one is still on
111 // prepare for the reception of new data
112 waitCursor(true);
113
114 // no new time range for zoom orders
115 TmfTimeRange trange = null;
116 // Time Range will be used to filter out events which are
117 // not visible in one pixel
118 trange = request.getRange();
119
120 // indicate if the data model needs to be cleared e.g. a new
121 // experiment is being selected
122 boolean clearData = request.isclearDataInd();
123 // Indicate if current data needs to be cleared and if so
124 // specify the new experiment time range that applies
125 ModelUpdatePrep(trange, clearData);
126 }
127 }
128
129 /*
130 * (non-Javadoc)
131 *
132 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
133 * processingCompleted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
134 */
135 @TmfSignalHandler
136 public void processingCompleted(RequestCompletedSignal signal) {
137 ILttngSyntEventRequest request = signal.getRequest();
138
139 if (request == null) {
140 return;
141 }
142
143 // Update wait cursor
144 waitCursor(false);
145
146 // No data refresh actions for cancelled requests.
147 if (request.isCancelled() || request.isFailed()) {
148 if (TraceDebug.isDEBUG()) {
149 TmfTimeRange trange = request.getRange();
150 if (request.isCancelled()) {
151 TraceDebug.debug("Request cancelled "
152 + trange.getStartTime() + "-" + trange.getEndTime()
153 + " Handled Events: " + request.getSynEventCount()
154 + " " + request.toString(), 15);
155 } else if (request.isFailed()) {
156 TraceDebug.debug("Request Failed " + trange.getStartTime()
157 + "-" + trange.getEndTime() + " Handled Events: "
158 + request.getSynEventCount() + " "
159 + request.toString());
160 }
161 }
162
163 return;
164 } else {
165 modelInputChanged(request, true);
166 }
167 }
168
169 /**
170 * Registers as listener of time selection from other views
171 *
172 * @param signal
173 */
174 public void synchToTime(TmfTimeSynchSignal signal) {
175 if (synch) {
176 Object source = signal.getSource();
177 if (signal != null && source != null && source != this) {
178 // Internal value is expected in nano seconds.
179 long selectedTime = signal.getCurrentTime().getValue();
180 if (tsfviewer != null) {
181 tsfviewer.setSelectedTime(selectedTime, true, source);
182 }
183 }
184 }
185 }
186
187 /**
188 * Process the reception of time window adjustment in this view if the
189 * source of the update is not this view.
190 *
191 * @param signal
192 * @param clearingData
193 */
194 public void synchToTimeRange(TmfRangeSynchSignal signal, boolean clearingData) {
195 if (synch) {
196 Object source = signal.getSource();
197 if (signal != null && source != null && source != this) {
198 // Internal value is expected in nano seconds.
199 TmfTimeRange trange = signal.getCurrentRange();
200 TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment();
201 if (experiment == null) {
202 TraceDebug.debug("Current selected experiment is null");
203 return;
204 }
205
206 // Clearing of process data is configurable
207 dataRequest(trange, experiment.getTimeRange(), clearingData);
208 }
209 }
210 }
211
212 /**
213 * Trigger time synchronisation to other views this method shall be called
214 * when a check has been performed to note that an actual change of time has
215 * been performed vs a pure re-selection of the same time
216 *
217 * @param time
218 * @param source
219 */
220 protected void synchTimeNotification(long time, Object source) {
221 // if synchronisation selected
222 if (synch) {
223 // Notify other views
224 TmfSignalManager.dispatchSignal(new TmfTimeSynchSignal(source, new LttngTimestamp(time)));
225 }
226 }
227
228 /**
229 * Common implementation of ITmfTimeSelectionListener, not used by all the
230 * views extending this abstract class
231 *
232 * @param event
233 */
234 protected void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) {
235 Object source = event.getSource();
236 if (source == null) {
237 return;
238 }
239
240 ParamsUpdater paramUpdater = getParamsUpdater();
241 Long savedSelTime = paramUpdater.getSelectedTime();
242
243 long selTimens = event.getSelectedTime();
244
245 // make sure the new selected time is different than saved before
246 // executing update
247 if (savedSelTime == null || savedSelTime != selTimens) {
248 // Notify listener views.
249 synchTimeNotification(selTimens, source);
250
251 // Update the parameter updater to save the selected time
252 paramUpdater.setSelectedTime(selTimens);
253
254 if (TraceDebug.isDEBUG()) {
255 TraceDebug.debug("Selected Time: " + new LttngTimestamp(selTimens) + "\n\t\t" + getName());
256 }
257 }
258 }
259
260 /**
261 * Common implementation of ITmfTimeScaleSelectionListener, not used by all
262 * the views extending this abstract class
263 *
264 * @param event
265 */
266 protected synchronized void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) {
267 // source needed to keep track of source values
268 Object source = event.getSource();
269
270 if (source != null) {
271 // Update the parameter updater before carrying out a read request
272 ParamsUpdater paramUpdater = getParamsUpdater();
273 boolean newParams = paramUpdater.processTimeScaleEvent(event);
274
275 if (newParams) {
276 // Read the updated time window
277 TmfTimeRange trange = paramUpdater.getTrange();
278 if (trange != null) {
279
280 // Notify listener views. to perform data requests
281 // upon this notification
282 synchTimeRangeNotification(trange, paramUpdater.getSelectedTime(), source);
283 }
284 }
285 }
286 }
287
288 /**
289 * Inform registered listeners about the new time range
290 *
291 * @param trange
292 * @param selectedTime
293 * @param source
294 */
295 protected void synchTimeRangeNotification(TmfTimeRange trange, Long selectedTime, Object source) {
296 // if synchronisation selected
297 if (synch) {
298 // Notify other views
299 TmfSignalManager.dispatchSignal(new TmfRangeSynchSignal(source, trange, new LttngTimestamp(selectedTime)));
300 }
301 }
302
303 /**
304 * @param zoomedTRange
305 * @param experimentTRange
306 */
307 public void dataRequest(TmfTimeRange zoomedTRange,
308 TmfTimeRange experimentTRange, boolean clearingData) {
309
310 // timeRange is the Experiment time range
311 boolean sent = processDataRequest(zoomedTRange, experimentTRange, clearingData);
312
313 if (sent) {
314 waitCursor(true);
315 }
316 }
317
318 /**
319 * send data request directly e.g. doesn't use a queue
320 *
321 * @param requestTrange
322 * @param listener
323 * @param experimentTRange
324 * @param processor
325 * @return
326 */
327 private boolean processDataRequest(TmfTimeRange requestTrange,
328 TmfTimeRange experimentTRange, boolean clearingData) {
329 // Validate input
330 if (requestTrange == null || experimentTRange == null) {
331 TraceDebug.debug("Invalid input");
332 return false;
333 }
334
335 LttngSyntEventRequest request = new LttngSyntEventRequest(
336 requestTrange, DEFAULT_OFFSET, TmfDataRequest.ALL_DATA,
337 DEFAULT_CHUNK, this, experimentTRange, getEventProcessor()) {
338
339 Long fCount = getSynEventCount();
340 ITransEventProcessor processor = getProcessor();
341 TmfTimestamp frunningTimeStamp;
342
343 /*
344 * (non-Javadoc)
345 *
346 * @see
347 * org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest#handleData
348 * ()
349 */
350 int handleDataCount = 0;
351 int handleDataValidCount = 0;
352 @Override
353 public void handleData() {
354 TmfEvent[] result = getData();
355
356 TmfEvent evt = (result.length > 0) ? result[0] : null;
357 handleDataCount++;
358 if (evt != null) {
359 handleDataValidCount++;
360 LttngSyntheticEvent synEvent = (LttngSyntheticEvent) evt;
361 // process event
362 SequenceInd indicator = synEvent.getSynType();
363 if (indicator == SequenceInd.BEFORE
364 || indicator == SequenceInd.AFTER) {
365 processor.process(evt, synEvent.getTraceModel());
366 } else if (indicator == SequenceInd.STARTREQ) {
367 handleRequestStarted();
368 } else if (indicator == SequenceInd.ENDREQ) {
369 processor.process(evt, synEvent.getTraceModel());
370 // handleCompleted();
371 }
372
373 if (indicator == SequenceInd.BEFORE) {
374 fCount++;
375 if (fCount != 0 && fCount % INPUT_CHANGED_REFRESH == 0) {
376 // send partial update
377 modelInputChanged(this, false);
378
379 if (TraceDebug.isDEBUG()) {
380 frunningTimeStamp = evt.getTimestamp();
381 TraceDebug.debug("handled: " + fCount + " sequence: " + synEvent.getSynType());
382 }
383
384 }
385 }
386 }
387 }
388
389 public void handleRequestStarted() {
390 notifyStarting();
391 }
392
393 @Override
394 public void done() {
395 if (TraceDebug.isDEBUG()) {
396 TraceDebug.debug("AbsTimeUpdateView: Received=" + handleDataCount + ", Valid=" + handleDataCount + ", fCount=" + fCount);
397 }
398 super.done();
399 }
400
401 @Override
402 public void handleCompleted() {
403 super.handleCompleted();
404
405 // Data is not complete and should be handled as such
406 if (isFailed() || isCancelled()) {
407 modelIncomplete(this);
408 }
409
410 if (TraceDebug.isDEBUG()) {
411 if (frunningTimeStamp != null) {
412 TraceDebug.debug("Last event time stamp: "
413 + frunningTimeStamp.getValue());
414 }
415 }
416 }
417 };
418
419 // obtain singleton core provider
420 LttngSyntheticEventProvider provider = LttngCoreProviderFactory
421 .getEventProvider();
422
423 // send the request to TMF
424 request.startRequestInd(provider);
425 request.setclearDataInd(clearingData);
426 return true;
427 }
428
429 /**
430 * Returns an initial smaller window to allow the user to select the area of
431 * interest
432 *
433 * @param experimentTRange
434 * @return
435 */
436 protected TmfTimeRange getInitTRange(TmfTimeRange experimentTRange) {
437 TmfTimestamp expStartTime = experimentTRange.getStartTime();
438 TmfTimestamp expEndTime = experimentTRange.getEndTime();
439 TmfTimestamp initialEndOfWindow = new LttngTimestamp(expStartTime
440 .getValue()
441 + INITIAL_WINDOW_OFFSET);
442 if (initialEndOfWindow.compareTo(expEndTime, false) < 0) {
443 return new TmfTimeRange(expStartTime, initialEndOfWindow);
444 }
445
446 // The original size of the experiment is smaller than proposed adjusted
447 // time
448 return experimentTRange;
449 }
450
451 /**
452 * Request the Time Analysis widget to enable or disable the wait cursor
453 * e.g. data request in progress or data request completed
454 *
455 * @param waitInd
456 */
457 protected void waitCursor(final boolean waitInd) {
458 if (tsfviewer != null) {
459 Display display = tsfviewer.getControl().getDisplay();
460
461 // Perform the updates on the UI thread
462 display.asyncExec(new Runnable() {
463 public void run() {
464 tsfviewer.waitCursor(waitInd);
465 }
466 });
467 }
468 }
469
470 /**
471 * View preparation to override the current local information
472 *
473 * @param timeRange
474 * - new total time range e.g. Experiment level
475 * @param clearAllData
476 */
477 protected void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) {
478 ItemContainer<?> itemContainer = getItemContainer();
479 if (clearAllData) {
480 // start fresh e.g. new experiment selected
481 itemContainer.clearItems();
482 } else {
483 // clear children but keep processes
484 itemContainer.clearChildren();
485 }
486
487 // Obtain the current resource array
488 ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems();
489
490 // clean up data and boundaries
491 displayModel(itemArr, -1, -1, false, -1, -1, null);
492
493 ParamsUpdater updater = getParamsUpdater();
494 if (updater != null) {
495 // Start over
496 updater.setEventsDiscarded(0);
497
498 // Update new visible time range if available
499 if (timeRange != null) {
500 updater.update(timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue());
501 }
502 }
503 }
504
505 /**
506 * Initialize the model and view before reloading items
507 *
508 * @param boundaryRange
509 * @param visibleRange
510 * @param source
511 */
512 protected void ModelUpdateInit(TmfTimeRange boundaryRange, TmfTimeRange visibleRange, Object source) {
513 // Update the view boundaries
514 if (boundaryRange != null) {
515 ItemContainer<?> itemContainer = getItemContainer();
516 if (itemContainer != null) {
517 itemContainer.clearItems();
518 // Obtain the current process array
519 ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems();
520
521 long startTime = boundaryRange.getStartTime().getValue();
522 long endTime = boundaryRange.getEndTime().getValue();
523
524 // Update the view part
525 displayModel(itemArr, startTime, endTime, true, visibleRange.getStartTime().getValue(), visibleRange
526 .getEndTime().getValue(), source);
527 }
528 }
529
530 // update the view filtering parameters
531 if (visibleRange != null) {
532 ParamsUpdater updater = getParamsUpdater();
533 if (updater != null) {
534 // Start over
535 updater.setEventsDiscarded(0);
536 // Update new visible time range if available
537 updater.update(visibleRange.getStartTime().getValue(), visibleRange.getEndTime().getValue());
538 }
539 }
540 }
541
542 /**
543 * Actions taken by the view to refresh its widget(s) with the updated data
544 * model
545 *
546 * @param request
547 * @param complete
548 * true: yes, false: partial update
549 */
550 protected void modelInputChanged(ILttngSyntEventRequest request, boolean complete) {
551 long experimentStartTime = -1;
552 long experimentEndTime = -1;
553 TmfTimeRange experimentTimeRange = request.getExperimentTimeRange();
554 if (experimentTimeRange != null) {
555 experimentStartTime = experimentTimeRange.getStartTime().getValue();
556 experimentEndTime = experimentTimeRange.getEndTime().getValue();
557 }
558
559 // Obtain the current resource list
560 ITmfTimeAnalysisEntry[] itemArr = getItemContainer().readItems();
561
562 if (itemArr != null) {
563 // Sort the array by pid
564 Arrays.sort(itemArr);
565
566 // Update the view part
567 displayModel(itemArr, experimentStartTime, experimentEndTime, false, request.getRange().getStartTime()
568 .getValue(), request.getRange().getEndTime().getValue(), request.getSource());
569 }
570
571 if (complete) {
572 // reselect to original time
573 ParamsUpdater paramUpdater = ResourceModelFactory.getParamsUpdater();
574 if (paramUpdater != null && tsfviewer != null) {
575 final Long selTime = paramUpdater.getSelectedTime();
576 if (selTime != null) {
577 TraceDebug.debug("View: " + getName() + "\n\t\tRestoring the selected time to: " + selTime);
578 Display display = tsfviewer.getControl().getDisplay();
579 display.asyncExec(new Runnable() {
580 public void run() {
581 tsfviewer.setSelectedTime(selTime, false, this);
582 }
583 });
584 }
585
586 if (TraceDebug.isDEBUG()) {
587 int eventCount = 0;
588 Long count = request.getSynEventCount();
589 for (int pos = 0; pos < itemArr.length; pos++) {
590 eventCount += itemArr[pos].getTraceEvents().size();
591 }
592
593 int discarded = getParamsUpdater().getEventsDiscarded();
594 int discardedOutofOrder = paramUpdater.getEventsDiscardedWrongOrder();
595 TmfTimeRange range = request.getRange();
596 StringBuilder sb = new StringBuilder("View: " + getName() + ", Events handled: " + count
597 + ", Events loaded in view: " + eventCount + ", Number of events discarded: " + discarded
598 + "\n\tNumber of events discarded with start time earlier than next good time: "
599 + discardedOutofOrder);
600
601 sb.append("\n\t\tRequested Time Range: " + range.getStartTime() + "-" + range.getEndTime());
602 sb.append("\n\t\tExperiment Time Range: " + experimentStartTime + "-" + experimentEndTime);
603 TraceDebug.debug(sb.toString());
604 }
605 }
606
607 }
608 }
609
610 // /**
611 // * Obtains the remainder fraction on unit Seconds of the entered value in
612 // * nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds
613 // can
614 // * be obtain by removing the last 9 digits: 1241207054 the fractional
615 // * portion of seconds, expressed in ns is: 171080214
616 // *
617 // * @param v
618 // * @return
619 // */
620 // protected String formatNs(long v) {
621 // StringBuffer str = new StringBuffer();
622 // boolean neg = v < 0;
623 // if (neg) {
624 // v = -v;
625 // str.append('-');
626 // }
627 //
628 // String strVal = String.valueOf(v);
629 // if (v < 1000000000) {
630 // return strVal;
631 // }
632 //
633 // // Extract the last nine digits (e.g. fraction of a S expressed in ns
634 // return strVal.substring(strVal.length() - 9);
635 // }
636
637 /**
638 * The request was stopped, the data is incomplete
639 *
640 * @param request
641 */
642 protected abstract void modelIncomplete(ILttngSyntEventRequest request);
643
644 /**
645 * Returns the Event processor instance related to a specific view
646 *
647 * @return
648 */
649 protected abstract ITransEventProcessor getEventProcessor();
650
651 /**
652 * To be overridden by some sub-classes although may not be needed in some
653 * e.g. statistics view
654 *
655 * @param items
656 * @param startBoundTime
657 * @param endBoundTime
658 * @param updateTimeBounds
659 * - Time bounds updated needed e.g. if a new Experiment or trace
660 * is selected
661 * @param startVisibleWindow
662 * @param endVisibleWindow
663 * @param source
664 */
665 protected abstract void displayModel(final ITmfTimeAnalysisEntry[] items, final long startBoundTime,
666 final long endBoundTime, final boolean updateTimeBounds, final long startVisibleWindow,
667 final long endVisibleWindow, final Object source);
668
669 /**
670 * To be overridden by some sub-classes although may not be needed in some
671 * e.g. statistics view
672 *
673 * @return
674 */
675 protected abstract ParamsUpdater getParamsUpdater();
676
677 /**
678 * Returns the model's item container
679 *
680 * @return
681 */
682 protected abstract ItemContainer<?> getItemContainer();
683 }
This page took 0.04528 seconds and 5 git commands to generate.