/*******************************************************************************
* 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 v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
*******************************************************************************/
package fr.inria.linuxtools.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.Nullable;
import fr.inria.linuxtools.statesystem.core.ITmfStateSystem;
import fr.inria.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule;
import fr.inria.linuxtools.tmf.core.exceptions.TmfAnalysisException;
import fr.inria.linuxtools.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
import fr.inria.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule;
import fr.inria.linuxtools.tmf.core.trace.ITmfTrace;
/**
* Analysis module to compute the statistics of a trace.
*
* @author Alexandre Montplaisir
* @since 3.0
*/
public class TmfStatisticsModule extends TmfAbstractAnalysisModule
implements ITmfAnalysisModuleWithStateSystems {
/** ID of this analysis module */
public static final String ID = "fr.inria.linuxtools.tmf.core.statistics.analysis"; //$NON-NLS-1$
/** The trace's statistics */
private ITmfStatistics fStatistics = null;
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.
*/
public void waitForInitialization() {
try {
fInitialized.await();
} catch (InterruptedException e) {}
}
// ------------------------------------------------------------------------
// 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 void setTrace(ITmfTrace trace) throws TmfAnalysisException {
super.setTrace(trace);
/*
* 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()!
*/
totalsModule.setTrace(trace);
eventTypesModule.setTrace(trace);
}
@Override
protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
ITmfTrace trace = getTrace();
if (trace == null) {
/* This analysis's trace should not be null when this is called */
throw new IllegalStateException();
}
IStatus status1 = totalsModule.schedule();
IStatus status2 = eventTypesModule.schedule();
if (!(status1.isOK() && status2.isOK())) {
cancelSubAnalyses();
return false;
}
/* Wait until the two modules are initialized */
totalsModule.waitForInitialization();
eventTypesModule.waitForInitialization();
ITmfStateSystem totalsSS = totalsModule.getStateSystem();
ITmfStateSystem eventTypesSS = eventTypesModule.getStateSystem();
if (totalsSS == null || eventTypesSS == null) {
/* Better safe than sorry... */
throw new IllegalStateException();
}
fStatistics = new TmfStateStatistics(totalsSS, eventTypesSS);
/* fStatistics is now set, consider this module initialized */
fInitialized.countDown();
/*
* The rest of this "execute" will encompass the "execute" of the two
* sub-analyzes.
*/
if (!(totalsModule.waitForCompletion(monitor) &&
eventTypesModule.waitForCompletion(monitor))) {
return false;
}
return true;
}
@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 Iterable<ITmfStateSystem> getStateSystems() {
List<ITmfStateSystem> list = new LinkedList<>();
list.add(totalsModule.getStateSystem());
list.add(eventTypesModule.getStateSystem());
return list;
}
}