blob: 32b759372649275e63b10f1cff8d71141ea86ff4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 École Polytechnique de Montréal
*
* 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
*******************************************************************************/
package org.eclipse.tracecompass.incubator.scripting.core.analysis;
import org.eclipse.ease.modules.ScriptParameter;
import org.eclipse.ease.modules.WrapToScript;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.internal.scripting.core.analysis.TmfScriptAnalysis;
import org.eclipse.tracecompass.incubator.internal.scripting.core.trace.ScriptEventRequest;
import org.eclipse.tracecompass.incubator.scripting.core.trace.ScriptEventsIterator;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
/**
* Analysis class that can be used with the scripts. It provides an event
* iterator, as well as backends to store data. Scripts can thus parse events
* and fill the backend appropriately.
*
* @author Geneviève Bastien
*/
public class ScriptedAnalysis {
private final ITmfTrace fTrace;
private final String fName;
private @Nullable ITmfStateSystemBuilder fStateSystem;
/**
* Constructor
*
* package-private because it is only expected to be constructed by the
* module.
*
* @param activeTrace
* The trace to associate with this analysis
* @param name
* The name of the analysis
*/
ScriptedAnalysis(ITmfTrace activeTrace, String name) {
fTrace = activeTrace;
fName = name;
}
/**
* Get a state system to go with this analysis. If an analysis of the same
* name already exists, it can be re-used instead of re-created.
*
* @param useExisting
* if <code>true</code>, any state system with the same name for
* the trace will be reused, otherwise, a new state system will
* be created
* @return A state system builder
*/
@WrapToScript
public @Nullable ITmfStateSystemBuilder getStateSystem(@ScriptParameter(defaultValue = "false") boolean useExisting) {
ITmfStateSystemBuilder stateSystem = fStateSystem;
if (stateSystem != null) {
return stateSystem;
}
TmfScriptAnalysis analysisModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, TmfScriptAnalysis.class, TmfScriptAnalysis.ID);
if (analysisModule == null) {
return null;
}
analysisModule.schedule();
analysisModule.waitForCompletion();
stateSystem = (ITmfStateSystemBuilder) analysisModule.getStateSystem(fName, useExisting);
fStateSystem = stateSystem;
return stateSystem;
}
/**
* Get an iterator to iterate chronologically through the events of the
* trace. To reduce overhead of passing all events to/from the script when
* only a subset of events is requested, the
* {@link ScriptEventsIterator#addEvent(String)} method can be used to set
* the events to filter.
*
* Thus, to iterate through a trace in a scripted analysis, one can just do
* the following snippet (javascript)
*
* <pre>
* var iter = analysis.getEventIterator();
*
* var event = null;
* while (iter.hasNext()) {
*
* event = iter.next();
*
* // Do something with the event
* }
* </pre>
*
* @return The event iterator, starting from the first event
*/
@WrapToScript
public ScriptEventsIterator getEventIterator() {
ScriptEventRequest scriptEventRequest = new ScriptEventRequest();
fTrace.sendRequest(scriptEventRequest);
return scriptEventRequest.getEventIterator();
}
/**
* Get the trace, not to be used by scripts.
*
* @return The trace
*/
public ITmfTrace getTrace() {
return fTrace;
}
/**
* Get the name of this analysis, not to be used by scripts
*
* @return The name of the analysis
*/
public String getName() {
return fName;
}
/**
* Make sure the analysis is complete and the state system, if any, is
* closed. It will close the state system at the end time of the trace if is
* has not been closed previously. If no state system was requested through
* the {@link #getStateSystem(boolean)} before hand, nothing will happen.
*/
public void complete() {
ITmfStateSystemBuilder stateSystem = fStateSystem;
if (stateSystem == null) {
return;
}
if (!stateSystem.waitUntilBuilt(0)) {
stateSystem.closeHistory(getTrace().getEndTime().toNanos());
}
}
/**
* Get whether this analysis is complete, ie, if a state systemw as
* requested by the {@link #getStateSystem(boolean)} method, then the state
* system has been closed.
*
* @return Whether the analysis is complete and the state system was closed
*/
public boolean isComplete() {
ITmfStateSystemBuilder stateSystem = fStateSystem;
if (stateSystem == null) {
return true;
}
return stateSystem.waitUntilBuilt(0);
}
}