lttng-control: Workaround for stderr problem in with SSH shell
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / statesystem / TmfStateSystemViewer.java
CommitLineData
17c73d10
GB
1/*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Florian Wininger - Initial API and implementation
11 * Alexandre Montplaisir - Refactoring, performance tweaks
12 * Bernd Hufmann - Updated signal handling
13 * Marc-Andre Laperle - Add time zone preference
14 * Geneviève Bastien - Moved state system explorer to use the abstract tree viewer
15 *******************************************************************************/
16
17package org.eclipse.linuxtools.tmf.ui.views.statesystem;
18
19import java.util.ArrayList;
20import java.util.List;
21
22import org.eclipse.jdt.annotation.NonNull;
23import org.eclipse.jface.viewers.AbstractTreeViewer;
24import org.eclipse.jface.viewers.Viewer;
25import org.eclipse.jface.viewers.ViewerComparator;
bcec0116
AM
26import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
27import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
28import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
29import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
30import org.eclipse.linuxtools.statesystem.core.interval.ITmfStateInterval;
31import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
17c73d10
GB
32import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
33import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal;
34import org.eclipse.linuxtools.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
17c73d10
GB
35import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
36import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
37import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
38import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
39import org.eclipse.linuxtools.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
40import org.eclipse.linuxtools.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
41import org.eclipse.linuxtools.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
42import org.eclipse.linuxtools.tmf.ui.viewers.tree.TmfTreeColumnData;
43import org.eclipse.linuxtools.tmf.ui.viewers.tree.TmfTreeViewerEntry;
44import org.eclipse.swt.SWT;
45import org.eclipse.swt.graphics.Color;
46import org.eclipse.swt.widgets.Composite;
47import org.eclipse.swt.widgets.Display;
48
49/**
50 * Displays the content of the state systems at the current time
51 *
52 * @author Florian Wininger
53 * @author Alexandre Montplaisir
54 * @author Geneviève Bastien
55 * @since 3.0
56 */
57public class TmfStateSystemViewer extends AbstractTmfTreeViewer {
58
59 private static final String EMPTY_STRING = ""; //$NON-NLS-1$
60 private boolean fFilterStatus = false;
61 private static final int DEFAULT_AUTOEXPAND = 2;
62
63 /* Order of columns */
64 private static final int ATTRIBUTE_NAME_COL = 0;
65 private static final int QUARK_COL = 1;
66 private static final int VALUE_COL = 2;
67 private static final int TYPE_COL = 3;
68 private static final int START_TIME_COL = 4;
69 private static final int END_TIME_COL = 5;
70 private static final int ATTRIBUTE_FULLPATH_COL = 6;
71
72 /**
73 * Base class to provide the labels for the tree viewer. Views extending
74 * this class typically need to override the getColumnText method if they
75 * have more than one column to display
76 */
77 protected static class StateSystemTreeLabelProvider extends TreeLabelProvider {
78
79 @Override
80 public String getColumnText(Object element, int columnIndex) {
81 if (element instanceof StateSystemEntry) {
82 StateSystemEntry entry = (StateSystemEntry) element;
83 switch (columnIndex) {
84 case ATTRIBUTE_NAME_COL:
85 return entry.getName();
86 case QUARK_COL:
87 return String.valueOf(entry.getQuark());
88 case VALUE_COL:
89 return entry.getValue();
90 case TYPE_COL:
91 return entry.getType();
92 case START_TIME_COL:
93 return entry.getStartTime();
94 case END_TIME_COL:
95 return entry.getEndTime();
96 case ATTRIBUTE_FULLPATH_COL:
97 return entry.getFullPath();
98 default:
99 return EMPTY_STRING;
100 }
101 }
102 return super.getColumnText(element, columnIndex);
103 }
104
105 @Override
106 public Color getBackground(Object element, int columnIndex) {
107 if (element instanceof StateSystemEntry) {
108 if (((StateSystemEntry) element).isModified()) {
109 return Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
110 }
111 }
112 return super.getBackground(element, columnIndex);
113 }
114 }
115
116 /**
117 * Constructor
118 *
119 * @param parent
120 * The parent containing this viewer
121 */
122 public TmfStateSystemViewer(Composite parent) {
123 super(parent, false);
124 this.setLabelProvider(new StateSystemTreeLabelProvider());
125 getTreeViewer().setAutoExpandLevel(DEFAULT_AUTOEXPAND);
126 }
127
128 @Override
129 protected ITmfTreeColumnDataProvider getColumnDataProvider() {
130 return new ITmfTreeColumnDataProvider() {
131
132 @Override
133 public List<TmfTreeColumnData> getColumnData() {
134 List<TmfTreeColumnData> columns = new ArrayList<>();
135 TmfTreeColumnData column = new TmfTreeColumnData(Messages.TreeNodeColumnLabel);
136 columns.add(column);
137 column.setComparator(new ViewerComparator() {
138 @Override
139 public int compare(Viewer viewer, Object e1, Object e2) {
140 TmfTreeViewerEntry n1 = (TmfTreeViewerEntry) e1;
141 TmfTreeViewerEntry n2 = (TmfTreeViewerEntry) e2;
142
143 return n1.getName().compareTo(n2.getName());
144 }
145 });
146 columns.add(new TmfTreeColumnData(Messages.QuarkColumnLabel));
147 columns.add(new TmfTreeColumnData(Messages.ValueColumnLabel));
148 columns.add(new TmfTreeColumnData(Messages.TypeColumnLabel));
149 columns.add(new TmfTreeColumnData(Messages.StartTimeColumLabel));
150 columns.add(new TmfTreeColumnData(Messages.EndTimeColumLabel));
151 columns.add(new TmfTreeColumnData(Messages.AttributePathColumnLabel));
152 return columns;
153 }
154
155 };
156 }
157
158 // ------------------------------------------------------------------------
159 // Operations
160 // ------------------------------------------------------------------------
161
162 @Override
59c8ff34 163 protected ITmfTreeViewerEntry updateElements(long start, long end, boolean selection) {
17c73d10
GB
164 if (getTrace() == null) {
165 return null;
166 }
167
59c8ff34 168 ITmfTreeViewerEntry root = getInput();
17c73d10 169
59c8ff34 170 if ((!selection) && (root != null)) {
17c73d10
GB
171 return null;
172 }
173
174 /*
175 * Build the entries if it is the first time or to show only modified
176 * values
177 */
59c8ff34
MAL
178 if (root == null || fFilterStatus) {
179 root = buildEntries(start);
180 } else if (root instanceof TmfTreeViewerEntry) {
17c73d10
GB
181 /*
182 * Update the values of the elements of the state systems at time
183 * 'start'
184 */
59c8ff34 185 updateEntriesList(((TmfTreeViewerEntry)root).getChildren(), start);
17c73d10
GB
186 }
187
59c8ff34 188 return root;
17c73d10
GB
189 }
190
59c8ff34
MAL
191 private ITmfTreeViewerEntry buildEntries(long timestamp) {
192 // 'Fake' root node
193 TmfTreeViewerEntry rootEntry = new TmfTreeViewerEntry(""); //$NON-NLS-1$
194
195 List<ITmfTreeViewerEntry> children = rootEntry.getChildren();
8148507e 196 for (final ITmfTrace currentTrace : TmfTraceManager.getTraceSetWithExperiment(getTrace())) {
17c73d10
GB
197 if (currentTrace == null) {
198 continue;
199 }
59c8ff34 200 buildEntriesForTrace(currentTrace, timestamp, children);
17c73d10 201 }
59c8ff34 202 return rootEntry;
17c73d10
GB
203 }
204
205 /*
206 * Update the values of the entries. It will also create trace and state
207 * system entries if they do not exist yet.
208 */
59c8ff34 209 private void updateEntriesList(List<ITmfTreeViewerEntry> entries, long timestamp) {
0f8687b4 210 for (final ITmfTrace trace : TmfTraceManager.getTraceSetWithExperiment(getTrace())) {
17c73d10
GB
211 if (trace == null) {
212 continue;
213 }
214 ITmfTreeViewerEntry traceEntry = null;
215 for (ITmfTreeViewerEntry entry : entries) {
216 if (entry.getName().equals(trace.getName())) {
217 traceEntry = entry;
218 }
219 }
220 if (traceEntry == null) {
221 traceEntry = buildEntriesForTrace(trace, timestamp, entries);
222 }
223
224 /* Find the state system entries for this trace */
225 Iterable<ITmfAnalysisModuleWithStateSystems> modules = trace.getAnalysisModulesOfClass(ITmfAnalysisModuleWithStateSystems.class);
226 for (ITmfAnalysisModuleWithStateSystems module : modules) {
227 module.schedule();
228 for (ITmfStateSystem ss : module.getStateSystems()) {
229 if (ss == null) {
230 continue;
231 }
232 ITmfTreeViewerEntry ssEntry = null;
233 for (ITmfTreeViewerEntry entry : traceEntry.getChildren()) {
234 if (entry.getName().equals(ss.getSSID())) {
235 ssEntry = entry;
236 }
237 }
238
239 if (ssEntry == null) {
240 /* The state system entry has not been built yet */
241 buildEntriesForStateSystem(ss, timestamp, (TmfTreeViewerEntry) traceEntry);
242 } else if (ssEntry.hasChildren()) {
243 /*
244 * Typical case at this point, update the data from the
245 * state system
246 */
247 updateEntriesForStateSystem(ss, timestamp, (TmfTreeViewerEntry) ssEntry);
248 } else {
249 /*
250 * The state system existed but entries were not filled,
251 * that would occur if for instance the values were out
252 * of range at the first query.
253 */
254 fillEntriesForStateSystem(ss, timestamp, (TmfTreeViewerEntry) ssEntry);
255 }
256 }
257 }
258 }
17c73d10
GB
259 }
260
261 @NonNull
262 private ITmfTreeViewerEntry buildEntriesForTrace(@NonNull ITmfTrace trace, long timestamp, @NonNull List<ITmfTreeViewerEntry> rootEntries) {
263 TmfTreeViewerEntry traceEntry = new TmfTreeViewerEntry(trace.getName());
264 rootEntries.add(traceEntry);
265
266 Iterable<ITmfAnalysisModuleWithStateSystems> modules = trace.getAnalysisModulesOfClass(ITmfAnalysisModuleWithStateSystems.class);
267 for (ITmfAnalysisModuleWithStateSystems module : modules) {
268 /* Just schedule the module, the data will be filled when available */
269 module.schedule();
270 for (ITmfStateSystem ss : module.getStateSystems()) {
271 if (ss == null) {
272 continue;
273 }
274 buildEntriesForStateSystem(ss, timestamp, traceEntry);
275 }
276 }
277 return traceEntry;
278 }
279
280 private void buildEntriesForStateSystem(ITmfStateSystem ss, long timestamp, TmfTreeViewerEntry traceEntry) {
281 TmfTreeViewerEntry ssEntry = new TmfTreeViewerEntry(ss.getSSID());
282 traceEntry.addChild(ssEntry);
283 fillEntriesForStateSystem(ss, timestamp, ssEntry);
284 }
285
286 private void fillEntriesForStateSystem(ITmfStateSystem ss, long timestamp, TmfTreeViewerEntry ssEntry) {
287 try {
288 addChildren(ss, ss.queryFullState(timestamp), -1, ssEntry, timestamp);
289 } catch (StateSystemDisposedException | TimeRangeException e) {
290 /* Nothing to do */
291 }
292 }
293
294 /**
295 * Add children node to an entry. It will create all necessary entries.
296 */
297 private void addChildren(ITmfStateSystem ss, List<ITmfStateInterval> fullState, int rootQuark, TmfTreeViewerEntry root, long timestamp) {
298 try {
299 for (int quark : ss.getSubAttributes(rootQuark, false)) {
300
301 ITmfStateInterval interval = fullState.get(quark);
302
303 StateSystemEntry entry = new StateSystemEntry(ss.getAttributeName(quark), quark, ss.getFullAttributePath(quark),
304 interval.getStateValue(),
305 new TmfTimestamp(interval.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE),
306 new TmfTimestamp(interval.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE));
307
308 /* Add this node's children recursively */
309 addChildren(ss, fullState, quark, entry, timestamp);
310
311 /**
312 * <pre>
313 * Do not add this entry to root if
314 * 1- the filter status is ON
315 * AND
316 * 2- the entry has no children
317 * AND
318 * 3- the start time is not the current timestamp
319 * </pre>
320 */
321 if (!(fFilterStatus && !entry.hasChildren() && (interval.getStartTime() != timestamp))) {
322 root.addChild(entry);
323 }
324 }
325
326 } catch (AttributeNotFoundException e) {
327 /* Should not happen, we're iterating on known attributes */
328 throw new RuntimeException();
329 }
330 }
331
332 private void updateEntriesForStateSystem(ITmfStateSystem ss, long timestamp, TmfTreeViewerEntry ssEntry) {
333 try {
334 updateChildren(ss, ss.queryFullState(timestamp), ssEntry);
335 } catch (StateSystemDisposedException e) {
336 } catch (TimeRangeException e) {
337 /* Mark all entries out of range */
338 markOutOfRange(ssEntry);
339 }
340 }
341
342 /**
343 * Update the values of existing entries.
344 */
345 private void updateChildren(ITmfStateSystem ss, List<ITmfStateInterval> fullState, ITmfTreeViewerEntry root) {
346 for (ITmfTreeViewerEntry entry : root.getChildren()) {
347 if (entry instanceof StateSystemEntry) {
348 /*
349 * FIXME: if new sub attributes were added since the element was
350 * built, then then will not be added
351 */
352 StateSystemEntry ssEntry = (StateSystemEntry) entry;
353 ITmfStateInterval interval = fullState.get(ssEntry.getQuark());
354 if (interval != null) {
355 ssEntry.update(interval.getStateValue(), new TmfTimestamp(interval.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE),
356 new TmfTimestamp(interval.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE));
357 }
358
359 /* Update this node's children recursively */
360 updateChildren(ss, fullState, ssEntry);
361 }
362 }
363 }
364
365 /**
366 * Set the entries as out of range
367 */
368 private void markOutOfRange(ITmfTreeViewerEntry root) {
369 for (ITmfTreeViewerEntry entry : root.getChildren()) {
370 if (entry instanceof StateSystemEntry) {
371 ((StateSystemEntry) entry).setOutOfRange();
372
373 /* Update this node's children recursively */
374 markOutOfRange(entry);
375 }
376 }
377 }
378
379 /**
380 * Set the filter status of the viewer. By default, all entries of all state
381 * system are present, and the values that changed since last refresh are
382 * shown in yellow. When the filter status is true, only the entries with
383 * values modified at current time are displayed.
384 */
385 public void changeFilterStatus() {
386 fFilterStatus = !fFilterStatus;
387 if (fFilterStatus) {
388 getTreeViewer().setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
389 } else {
390 getTreeViewer().setAutoExpandLevel(DEFAULT_AUTOEXPAND);
391 clearContent();
392 }
393 updateContent(getSelectionBeginTime(), getSelectionEndTime(), true);
394 }
395
396 /**
397 * Update the display to use the updated timestamp format
398 *
399 * @param signal
400 * the incoming signal
401 */
402 @TmfSignalHandler
403 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
404 updateContent(getSelectionBeginTime(), getSelectionEndTime(), true);
405 }
406
407 private class StateSystemEntry extends TmfTreeViewerEntry {
408
409 private final int fQuark;
410 private final String fFullPath;
411 private @NonNull TmfTimestamp fStart;
412 private @NonNull TmfTimestamp fEnd;
413 private ITmfStateValue fValue;
414 private boolean fModified = false;
415 private boolean fOutOfRange = false;
416
417 public StateSystemEntry(String name, int quark, String fullPath, ITmfStateValue value, @NonNull TmfTimestamp start, @NonNull TmfTimestamp end) {
418 super(name);
419 fQuark = quark;
420 fFullPath = fullPath;
421 fStart = start;
422 fEnd = end;
423 fValue = value;
424 }
425
426 public int getQuark() {
427 return fQuark;
428 }
429
430 public String getFullPath() {
431 return fFullPath;
432 }
433
434 public String getStartTime() {
435 if (fOutOfRange) {
436 return EMPTY_STRING;
437 }
438 return fStart.toString();
439 }
440
441 public String getEndTime() {
442 if (fOutOfRange) {
443 return EMPTY_STRING;
444 }
445 return fEnd.toString();
446 }
447
448 public String getValue() {
449 if (fOutOfRange) {
450 return Messages.OutOfRangeMsg;
451 }
452 switch (fValue.getType()) {
453 case INTEGER:
454 case LONG:
455 case DOUBLE:
456 case STRING:
457 return fValue.toString();
458 case NULL:
459 default:
460 return EMPTY_STRING;
461 }
462 }
463
464 public String getType() {
465 if (fOutOfRange) {
466 return EMPTY_STRING;
467 }
468 switch (fValue.getType()) {
469 case INTEGER:
470 return Messages.TypeInteger;
471 case LONG:
472 return Messages.TypeLong;
473 case DOUBLE:
474 return Messages.TypeDouble;
475 case STRING:
476 return Messages.TypeString;
477 case NULL:
478 default:
479 return EMPTY_STRING;
480 }
481 }
482
483 public boolean isModified() {
484 return fModified;
485 }
486
487 public void update(ITmfStateValue value, @NonNull TmfTimestamp start, @NonNull TmfTimestamp end) {
488 fModified = false;
489 fOutOfRange = false;
490 if (!start.equals(fStart)) {
491 fModified = true;
492 fStart = start;
493 fEnd = end;
494 fValue = value;
495 }
496 }
497
498 public void setOutOfRange() {
499 fModified = false;
500 fOutOfRange = true;
501 }
502 }
503}
This page took 0.049688 seconds and 5 git commands to generate.