X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=org.eclipse.linuxtools.tmf.ui%2Fsrc%2Forg%2Feclipse%2Flinuxtools%2Ftmf%2Fui%2Fviewers%2Fstatistics%2FTmfStatisticsViewer.java;h=52d782a0fbbf3cc2189cc5f76dae4cfda1932bc6;hb=d6b46913ad62aa237e5c9b76b33e698d893110ed;hp=d15f0f281b9e4781a89b3a1bb57e4a77070ef7c8;hpb=3c934968638ac80923b6feac74fa8889e028fbd0;p=deliverable%2Ftracecompass.git diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsViewer.java index d15f0f281b..52d782a0fb 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsViewer.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/statistics/TmfStatisticsViewer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Ericsson + * Copyright (c) 2012, 2013 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -8,35 +8,41 @@ * * Contributors: * Mathieu Denis - Initial API and implementation + * Alexandre Montplaisir - Port to ITmfStatistics provider + * Patrick Tasse - Support selection range *******************************************************************************/ package org.eclipse.linuxtools.tmf.ui.viewers.statistics; import java.util.List; +import java.util.Map; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.linuxtools.tmf.core.component.TmfComponent; -import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; -import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp; -import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; -import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal; -import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest; import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal; +import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics; +import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment; +import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer; -import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.AbsTmfStatisticsTree; import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider; import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData; import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider; -import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseStatisticsTree; +import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTree; +import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager; import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode; -import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeRootFactory; import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider; +import org.eclipse.linuxtools.tmf.ui.views.statistics.TmfStatisticsModule; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -59,15 +65,10 @@ import org.eclipse.swt.widgets.Listener; */ public class TmfStatisticsViewer extends TmfViewer { - /** - * The initial window span (in nanoseconds) - */ - public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec - /** * Timestamp scale (nanosecond) */ - public static final byte TIME_SCALE = -9; + public static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE; /** * Default PAGE_SIZE for background requests. @@ -79,16 +80,6 @@ public class TmfStatisticsViewer extends TmfViewer { */ protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L; - /** - * Stores the request to the experiment - */ - protected TmfStatisticsRequest fRequest = null; - - /** - * Stores the ranged request to the experiment - */ - protected TmfStatisticsRequest fRequestRange = null; - /** * The actual tree viewer to display */ @@ -97,7 +88,7 @@ public class TmfStatisticsViewer extends TmfViewer { /** * The statistics tree linked to this viewer */ - protected AbsTmfStatisticsTree fStatisticsData; + protected TmfStatisticsTree fStatisticsData; /** * Update synchronization parameter (used for streaming): Update busy @@ -127,6 +118,16 @@ public class TmfStatisticsViewer extends TmfViewer { */ protected final Object fStatisticsRangeUpdateSyncObj = new Object(); + /** + * The trace that is displayed by this viewer + */ + protected ITmfTrace fTrace; + + /** + * Stores the requested time range. + */ + protected TmfTimeRange fRequestedTimerange; + /** * Indicates to process all events */ @@ -143,12 +144,7 @@ public class TmfStatisticsViewer extends TmfViewer { private int fInstanceNb; /** - * The trace that is displayed by this viewer - */ - private ITmfTrace fTrace; - - /** - * Object to store the cursor while waiting for the experiment to load + * Object to store the cursor while waiting for the trace to load */ private Cursor fWaitCursor = null; @@ -160,16 +156,20 @@ public class TmfStatisticsViewer extends TmfViewer { private int fWaitCursorCount = 0; /** - * Tells to send a time range request when the experiment gets updated. + * Tells to send a time range request when the trace gets updated. */ private boolean fSendRangeRequest = true; + /** Reference to the trace manager */ + private final TmfTraceManager fTraceManager; + /** * Empty constructor. To be used in conjunction with * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)} */ public TmfStatisticsViewer() { super(); + fTraceManager = TmfTraceManager.getInstance(); } /** @@ -186,6 +186,7 @@ public class TmfStatisticsViewer extends TmfViewer { */ public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) { init(parent, viewerName, trace); + fTraceManager = TmfTraceManager.getInstance(); } /** @@ -205,46 +206,39 @@ public class TmfStatisticsViewer extends TmfViewer { fInstanceNb = fCountInstance; fTrace = trace; - // The viewer will process all events if he is assigned to the experiment + // The viewer will process all events if he is assigned to an experiment fProcessAll = (trace instanceof TmfExperiment); initContent(parent); initInput(); } - /* - * (non-Javadoc) - * - * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose() - */ @Override public void dispose() { super.dispose(); if (fWaitCursor != null) { fWaitCursor.dispose(); } - /* - * Make sure there is no request running before removing the statistics - * tree - */ - cancelOngoingRequest(fRequestRange); - cancelOngoingRequest(fRequest); - // Clean the model - TmfStatisticsTreeRootFactory.removeStatTreeRoot(getTreeID()); + // Clean the model for this viewer + TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID()); } + // ------------------------------------------------------------------------ + // Signal handlers + // ------------------------------------------------------------------------ + /** - * Handles the signal about new experiment range. + * Handles the signal about new trace range. * * @param signal - * The experiment range updated signal + * The trace range updated signal */ @TmfSignalHandler - public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) { - TmfExperiment experiment = signal.getExperiment(); + public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) { + ITmfTrace trace = signal.getTrace(); // validate - if (!experiment.equals(TmfExperiment.getCurrentExperiment())) { + if (!isListeningTo(trace)) { return; } @@ -252,64 +246,52 @@ public class TmfStatisticsViewer extends TmfViewer { // Sends the time range request only once from this method. if (fSendRangeRequest) { fSendRangeRequest = false; - // Calculate the selected time range to request - long startTime = signal.getRange().getStartTime().normalize(0, TIME_SCALE).getValue(); - TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE); - TmfTimestamp endTS = new TmfTimestamp(startTime + INITIAL_WINDOW_SPAN, TIME_SCALE); - TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS); - - requestTimeRangeData(experiment, timeRange); + ITmfTimestamp begin = fTraceManager.getSelectionBeginTime(); + ITmfTimestamp end = fTraceManager.getSelectionEndTime(); + TmfTimeRange timeRange = new TmfTimeRange(begin, end); + requestTimeRangeData(trace, timeRange); } } - requestData(experiment, signal.getRange()); + requestData(trace, signal.getRange()); } /** - * Handles the experiment updated signal. This will detect new events in - * case the indexing is not coalesced with a statistics request. + * Handles the time range updated signal. It updates the time range + * statistics. * * @param signal - * The experiment updated signal + * Contains the information about the new selected time range. + * @deprecated + * As of 2.1, use {@link #timeSynchUpdated(TmfTimeSynchSignal)} */ + @Deprecated @TmfSignalHandler - public void experimentUpdated(TmfExperimentUpdatedSignal signal) { - TmfExperiment experiment = signal.getExperiment(); - if (!experiment.equals(TmfExperiment.getCurrentExperiment())) { - return; - } - - long nbEvents = 0; - if (fRequest != null) { - nbEvents = fRequest.getLastEventIndex(); - } - /* - * In the normal case, the statistics request is coalesced with indexing - * and the number of events are the same, there is nothing to do. But if - * it's not the case, trigger a new request to count the new events. - */ - if (nbEvents < experiment.getNbEvents()) { - requestData(experiment, experiment.getTimeRange()); - } + public void timeRangeUpdated(TmfRangeSynchSignal signal) { } /** - * * Handles the time range updated signal. It updates the time range + * Handles the time synch updated signal. It updates the time range * statistics. * * @param signal * Contains the information about the new selected time range. + * @since 2.1 */ @TmfSignalHandler - public void timeRangeUpdated(TmfRangeSynchSignal signal) { - /* - * It is possible that the time range changes while a request is - * processing. - */ - cancelOngoingRequest(fRequestRange); - - requestTimeRangeData(TmfExperiment.getCurrentExperiment(), signal.getCurrentRange()); + public void timeSynchUpdated(TmfTimeSynchSignal signal) { + if (fTrace == null) { + return; + } + ITmfTimestamp begin = signal.getBeginTime(); + ITmfTimestamp end = signal.getEndTime(); + TmfTimeRange timeRange = new TmfTimeRange(begin, end); + requestTimeRangeData(fTrace, timeRange); } + // ------------------------------------------------------------------------ + // Class methods + // ------------------------------------------------------------------------ + /* * Returns the primary control associated with this viewer. * @@ -354,9 +336,9 @@ public class TmfStatisticsViewer extends TmfViewer { * * @return a TmfStatisticsData object. */ - public AbsTmfStatisticsTree getStatisticData() { + public TmfStatisticsTree getStatisticData() { if (fStatisticsData == null) { - fStatisticsData = new TmfBaseStatisticsTree(); + fStatisticsData = new TmfStatisticsTree(); } return fStatisticsData; } @@ -410,8 +392,9 @@ public class TmfStatisticsViewer extends TmfViewer { * * @param request * The request to be canceled + * @since 3.0 */ - protected void cancelOngoingRequest(ITmfDataRequest request) { + protected void cancelOngoingRequest(ITmfEventRequest request) { if (request != null && !request.isCompleted()) { request.cancel(); } @@ -537,28 +520,19 @@ public class TmfStatisticsViewer extends TmfViewer { /** * Initializes the input for the tree viewer. - * - * @param input - * The input of this viewer, or null if none */ protected void initInput() { String treeID = getTreeID(); - TmfStatisticsTreeNode experimentTreeNode; - if (TmfStatisticsTreeRootFactory.containsTreeRoot(treeID)) { - // The experiment root is already present - experimentTreeNode = TmfStatisticsTreeRootFactory.getStatTreeRoot(treeID); + TmfStatisticsTreeNode statisticsTreeNode; + if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) { + // The statistics root is already present + statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID); // Checks if the trace is already in the statistics tree. - int numNodeTraces = experimentTreeNode.getNbChildren(); - - int numTraces = 1; - ITmfTrace[] trace = { fTrace }; - // For experiment, gets all the traces within it - if (fTrace instanceof TmfExperiment) { - TmfExperiment experiment = (TmfExperiment) fTrace; - numTraces = experiment.getTraces().length; - trace = experiment.getTraces(); - } + int numNodeTraces = statisticsTreeNode.getNbChildren(); + + ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace); + int numTraces = traces.length; if (numTraces == numNodeTraces) { boolean same = true; @@ -567,8 +541,8 @@ public class TmfStatisticsViewer extends TmfViewer { * previously selected. */ for (int i = 0; i < numTraces; i++) { - String traceName = trace[i].getName(); - if (!experimentTreeNode.containsChild(traceName)) { + String traceName = traces[i].getName(); + if (!statisticsTreeNode.containsChild(traceName)) { same = false; break; } @@ -576,38 +550,38 @@ public class TmfStatisticsViewer extends TmfViewer { if (same) { // No need to reload data, all traces are already loaded - fTreeViewer.setInput(experimentTreeNode); + fTreeViewer.setInput(statisticsTreeNode); return; } // Clears the old content to start over - experimentTreeNode.reset(); + statisticsTreeNode.reset(); } } else { // Creates a new tree - experimentTreeNode = TmfStatisticsTreeRootFactory.addStatsTreeRoot(treeID, getStatisticData()); + statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData()); } // Sets the input to a clean data model - fTreeViewer.setInput(experimentTreeNode); + fTreeViewer.setInput(statisticsTreeNode); resetUpdateSynchronization(); } /** - * Tells if the viewer is listening to a trace from the selected experiment. + * Tells if the viewer is listening to a trace. * - * @param traceName + * @param trace * The trace that the viewer may be listening * @return true if the viewer is listening to the trace, false otherwise */ - protected boolean isListeningTo(String traceName) { - if (fProcessAll || traceName.equals(fTrace.getName())) { + protected boolean isListeningTo(ITmfTrace trace) { + if (fProcessAll || trace == fTrace) { return true; } return false; } /** - * Called when an experiment request has been completed successfully. + * Called when an trace request has been completed successfully. * * @param global * Tells if the request is a global or time range (partial) @@ -622,7 +596,7 @@ public class TmfStatisticsViewer extends TmfViewer { } /** - * Called when an experiment request has failed or has been cancelled. + * Called when an trace request has failed or has been cancelled. * * @param isGlobalRequest * Tells if the request is a global or time range (partial) @@ -644,60 +618,169 @@ public class TmfStatisticsViewer extends TmfViewer { } /** - * Sends the request to the experiment for the whole trace + * Sends the request to the trace for the whole trace * - * @param experiment - * The experiment used to send the request - * @param range - * The range to request to the experiment - */ - protected void requestData(TmfExperiment experiment, TmfTimeRange range) { - // Check if an update is already ongoing - if (checkUpdateBusy(range)) { + * @param trace + * The trace used to send the request + * @param timeRange + * The range to request to the trace + */ + protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) { + buildStatisticsTree(trace, timeRange, true); + } + + /** + * Sends the time range request from the trace + * + * @param trace + * The trace used to send the request + * @param timeRange + * The range to request to the trace + */ + protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) { + fRequestedTimerange = timeRange; + buildStatisticsTree(trace, timeRange, false); + } + + /** + * Requests all the data of the trace to the state system which + * contains information about the statistics. + * + * Since the viewer may be listening to multiple traces, it may receive + * an experiment rather than a single trace. The filtering is done with the + * method {@link #isListeningTo(String trace)}. + * + * @param trace + * The trace for which a request must be done + * @param timeRange + * The time range that will be requested to the state system + * @param isGlobal + * Tells if the request is for the global event count or the + * partial one. + */ + private void buildStatisticsTree(final ITmfTrace trace, final TmfTimeRange timeRange, final boolean isGlobal) { + final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID()); + final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID()); + if (statsData == null) { return; } - long index = 0; - /* - * Sets the index to the last event retrieved from the experiment during - * the last request. - */ - if (fRequest != null) { - index = fRequest.getLastEventIndex(); - } + synchronized (statsData) { + if (isGlobal) { + statTree.resetGlobalValue(); + } else { + statTree.resetTimeRangeValue(); + } - fRequest = new TmfStatisticsRequest(this, range, index, true); - waitCursor(true); - experiment.sendRequest(fRequest); + for (final ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) { + if (!isListeningTo(aTrace)) { + continue; + } + + /* Retrieve the statistics object */ + final TmfStatisticsModule statsMod = aTrace.getAnalysisModuleOfClass(TmfStatisticsModule.class, TmfStatisticsModule.ID); + if (statsMod == null) { + /* No statistics module available for this trace */ + continue; + } + + /* Run the potentially long queries in a separate thread */ + Thread statsThread = new Thread("Statistics update") { //$NON-NLS-1$ + @Override + public void run() { + /* Wait until the analysis is ready */ + if (!statsMod.waitForCompletion(new NullProgressMonitor())) { + return; + } + + ITmfStatistics stats = statsMod.getStatistics(); + if (stats == null) { + /* It should have worked, but didn't */ + return; + } + + /* + * The generic statistics are stored in nanoseconds, so + * we must make sure the time range is scaled correctly. + */ + long start = timeRange.getStartTime().normalize(0, TIME_SCALE).getValue(); + long end = timeRange.getEndTime().normalize(0, TIME_SCALE).getValue(); + + Map map = stats.getEventTypesInRange(start, end); + updateStats(isGlobal, map); + } + }; + statsThread.start(); + return; + } + } } /** - * Sends the time range request from the experiment + * Whenever a trace's statistics back-end finishes computing the statistics + * for a given interval, it will send the StatsUpdated signal. This method + * will receive this signal and update the statistics view accordingly. * - * @param experiment - * The experiment used to send the request - * @param range - * The range to request to the experiment + * @param sig + * The signal that is received */ - protected void requestTimeRangeData(TmfExperiment experiment, TmfTimeRange range) { - resetTimeRangeValue(); - fRequestRange = new TmfStatisticsRequest(this, range, 0, false); - waitCursor(true); - experiment.sendRequest(fRequestRange); + private void updateStats(boolean isGlobal, Map eventsPerType) { + + final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID()); + Map map = eventsPerType; + String name = fTrace.getName(); + + /* + * "Global", "partial", "total", etc., it's all very confusing... + * + * The base view shows the total count for the trace and for + * each even types, organized in columns like this: + * + * | Global | Time range | + * trace name | A | B | + * Event Type | | | + * | C | D | + * | ... | ... | + * ... | | | + * + * Here, we called the cells like this: + * A : GlobalTotal + * B : TimeRangeTotal + * C : GlobalTypeCount(s) + * D : TimeRangeTypeCount(s) + */ + + /* Fill in an the event counts (either cells C or D) */ + for (Map.Entry entry : map.entrySet()) { + statsData.setTypeCount(name, entry.getKey(), isGlobal, entry.getValue()); + } + + /* + * Calculate the totals (cell A or B, depending if isGlobal). We will + * use the results of the previous request instead of sending another + * one. + */ + long globalTotal = 0; + for (long val : map.values()) { + globalTotal += val; + } + statsData.setTotal(name, isGlobal, globalTotal); + + modelComplete(isGlobal); } /** * Resets the number of events within the time range */ protected void resetTimeRangeValue() { - TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeRootFactory.getStatTreeRoot(getTreeID()); + TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID()); if (treeModelRoot != null && treeModelRoot.hasChildren()) { treeModelRoot.resetTimeRangeValue(); } } /** - * When the experiment is loading the cursor will be different so the user + * When the trace is loading the cursor will be different so the user * knows that the processing is not finished yet. * * Calls to this method are stacked. @@ -795,7 +878,7 @@ public class TmfStatisticsViewer extends TmfViewer { fStatisticsUpdateBusy = false; if (fStatisticsUpdatePending) { fStatisticsUpdatePending = false; - requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange); + requestData(fTrace, fStatisticsUpdateRange); fStatisticsUpdateRange = null; } }