blob: 47539118466196ba962c92bbe1b929f2c77332fb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2014 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.tmf.core.statistics;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
* Analysis module to compute the statistics of a trace.
*
* @author Alexandre Montplaisir
*/
public class TmfStatisticsModule extends TmfAbstractAnalysisModule
implements ITmfAnalysisModuleWithStateSystems {
/** ID of this analysis module */
public static final @NonNull String ID = "org.eclipse.linuxtools.tmf.core.statistics.analysis"; //$NON-NLS-1$
/** The trace's statistics */
private ITmfStatistics fStatistics = null;
private boolean fInitializationSucceeded;
private final TmfStateSystemAnalysisModule totalsModule = new TmfStatisticsTotalsModule();
private final TmfStateSystemAnalysisModule eventTypesModule = new TmfStatisticsEventTypesModule();
private final CountDownLatch fInitialized = new CountDownLatch(1);
/**
* Constructor
*/
public TmfStatisticsModule() {
super();
}
/**
* Get the statistics object built by this analysis
*
* @return The ITmfStatistics object
*/
@Nullable
public ITmfStatistics getStatistics() {
return fStatistics;
}
/**
* Wait until the analyses/state systems underneath are ready to be queried.
* @since 2.0
*/
@Override
public boolean waitForInitialization() {
try {
fInitialized.await();
} catch (InterruptedException e) {
return false;
}
return fInitializationSucceeded;
}
// ------------------------------------------------------------------------
// TmfAbstractAnalysisModule
// ------------------------------------------------------------------------
@Override
public void dispose() {
/*
* The sub-analyses are not registered to the trace directly, so we need
* to tell them when the trace is disposed.
*/
super.dispose();
totalsModule.dispose();
eventTypesModule.dispose();
}
@Override
public boolean setTrace(ITmfTrace trace) throws TmfAnalysisException {
if (!super.setTrace(trace)) {
return false;
}
/*
* Since these sub-analyzes are not built from an extension point, we
* have to assign the trace ourselves. Very important to do so before
* calling schedule()!
*/
if (!totalsModule.setTrace(trace)) {
return false;
}
return eventTypesModule.setTrace(trace);
}
@Override
protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
ITmfTrace trace = getTrace();
if (trace == null) {
/* This analysis was cancelled in the meantime */
analysisReady(false);
return false;
}
IStatus status1 = totalsModule.schedule();
IStatus status2 = eventTypesModule.schedule();
if (!(status1.isOK() && status2.isOK())) {
cancelSubAnalyses();
analysisReady(false);
return false;
}
/* Wait until the two modules are initialized */
if (!totalsModule.waitForInitialization() || !eventTypesModule.waitForInitialization()) {
analysisReady(false);
return false;
}
ITmfStateSystem totalsSS = totalsModule.getStateSystem();
ITmfStateSystem eventTypesSS = eventTypesModule.getStateSystem();
if (totalsSS == null || eventTypesSS == null) {
/* This analysis was cancelled in the meantime */
analysisReady(false);
throw new IllegalStateException("TmfStatisticsModule : Sub-modules initialization succeeded but there is a null state system."); //$NON-NLS-1$
}
fStatistics = new TmfStateStatistics(totalsSS, eventTypesSS);
/* fStatistics is now set, consider this module initialized */
analysisReady(true);
/*
* The rest of this "execute" will encompass the "execute" of the two
* sub-analyzes.
*/
return totalsModule.waitForCompletion(monitor) &&
eventTypesModule.waitForCompletion(monitor);
}
/**
* Make the module available and set whether the initialization went well or
* not. If not, no state system is available and
* {@link #waitForInitialization()} should return false.
*
* @param success
* True if the initialization went well, false otherwise
*/
private void analysisReady(boolean succeeded) {
fInitializationSucceeded = succeeded;
fInitialized.countDown();
}
@Override
protected void canceling() {
/*
* FIXME The "right" way to cancel state system construction is not
* available yet...
*/
cancelSubAnalyses();
ITmfStatistics stats = fStatistics;
if (stats != null) {
stats.dispose();
}
}
private void cancelSubAnalyses() {
totalsModule.cancel();
eventTypesModule.cancel();
}
// ------------------------------------------------------------------------
// ITmfStateSystemAnalysisModule
// ------------------------------------------------------------------------
@Override
public ITmfStateSystem getStateSystem(String id) {
switch (id) {
case TmfStatisticsTotalsModule.ID:
return totalsModule.getStateSystem();
case TmfStatisticsEventTypesModule.ID:
return eventTypesModule.getStateSystem();
default:
return null;
}
}
@Override
public @NonNull Iterable<@NonNull ITmfStateSystem> getStateSystems() {
List<@NonNull ITmfStateSystem> list = new LinkedList<>();
ITmfStateSystem totalsStateSystem = totalsModule.getStateSystem();
if (totalsStateSystem != null) {
list.add(totalsStateSystem);
}
ITmfStateSystem eventTypesStateSystem = eventTypesModule.getStateSystem();
if (eventTypesStateSystem != null) {
list.add(eventTypesStateSystem);
}
return list;
}
}