package org.eclipse.tracecompass.tmf.core.analysis;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.osgi.util.NLS;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.tmf.core.Activator;
+import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisRequirement.ValuePriorityLevel;
import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
* behavior to some methods of the analysis module
*
* @author Geneviève Bastien
- * @since 3.0
*/
+@NonNullByDefault
public abstract class TmfAbstractAnalysisModule extends TmfComponent implements IAnalysisModule {
- private String fName, fId;
+ private @Nullable String fId;
private boolean fAutomatic = false, fStarted = false;
- private ITmfTrace fTrace;
+ private volatile @Nullable ITmfTrace fTrace;
private final Map<String, Object> fParameters = new HashMap<>();
private final List<String> fParameterNames = new ArrayList<>();
private final List<IAnalysisOutput> fOutputs = new ArrayList<>();
private List<IAnalysisParameterProvider> fParameterProviders = new ArrayList<>();
- private Job fJob = null;
+ private @Nullable Job fJob = null;
private final Object syncObj = new Object();
@Override
public String getName() {
- return fName;
+ return super.getName();
}
@Override
public void setName(String name) {
- fName = name;
+ super.setName(name);
}
@Override
}
@Override
- @NonNull
public String getId() {
String id = fId;
if (id == null) {
- id = new String(this.getClass().getCanonicalName());
+ id = this.getClass().getCanonicalName();
+ if (id == null) {
+ /*
+ * Some types, like anonymous classes, don't have a canonical
+ * name. Just use the default name instead.
+ */
+ id = checkNotNull(this.getClass().getName());
+ }
fId = id;
}
return id;
fAutomatic = auto;
}
+ /**
+ * @since 1.0
+ */
@Override
- public void setTrace(ITmfTrace trace) throws TmfAnalysisException {
- if (trace == null) {
- throw new TmfAnalysisException(Messages.TmfAbstractAnalysisModule_NullTrace);
- }
+ public boolean setTrace(ITmfTrace trace) throws TmfAnalysisException {
if (fTrace != null) {
throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_TraceSetMoreThanOnce, getName()));
}
+ TmfCoreTracer.traceAnalysis(getId(), trace, "setting trace for analysis"); //$NON-NLS-1$
+
/* Check that analysis can be executed */
if (!canExecute(trace)) {
- throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute, getName()));
+ return false;
}
fTrace = trace;
/* Get the parameter providers for this trace */
- fParameterProviders = TmfAnalysisManager.getParameterProviders(this, fTrace);
+ fParameterProviders = TmfAnalysisManager.getParameterProviders(this, trace);
for (IAnalysisParameterProvider provider : fParameterProviders) {
+ TmfCoreTracer.traceAnalysis(getId(), trace, "registered to parameter provider " + provider.getName()); //$NON-NLS-1$
provider.registerModule(this);
}
resetAnalysis();
fStarted = false;
+ return true;
}
/**
*
* @return The trace
*/
- protected ITmfTrace getTrace() {
+ protected @Nullable ITmfTrace getTrace() {
return fTrace;
}
}
@Override
- public synchronized void setParameter(String name, Object value) {
+ public synchronized void setParameter(String name, @Nullable Object value) {
if (!fParameterNames.contains(name)) {
throw new RuntimeException(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, name, getName()));
}
}
@Override
- public Object getParameter(String name) {
+ public @Nullable Object getParameter(String name) {
Object paramValue = fParameters.get(name);
/* The parameter is not set, maybe it can be provided by someone else */
if ((paramValue == null) && (fTrace != null)) {
}
@Override
- public boolean canExecute(@NonNull ITmfTrace trace) {
+ public boolean canExecute(ITmfTrace trace) {
for (TmfAnalysisRequirement requirement : getAnalysisRequirements()) {
if (!requirement.isFulfilled(trace)) {
return false;
* Set the countdown latch back to 1 so the analysis can be executed again
*/
protected void resetAnalysis() {
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "reset: ready for execution"); //$NON-NLS-1$
fFinishedLatch.countDown();
fFinishedLatch = new CountDownLatch(1);
}
* It has to be called inside a synchronized block
*/
private void setAnalysisCompleted() {
- fStarted = false;
- fJob = null;
- fFinishedLatch.countDown();
+ synchronized (syncObj) {
+ fStarted = false;
+ fJob = null;
+ fFinishedLatch.countDown();
+ }
}
/**
@Override
public final void cancel() {
synchronized (syncObj) {
- if (fJob != null) {
- if (fJob.cancel()) {
- fAnalysisCancelled = true;
- setAnalysisCompleted();
- }
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "cancelled by application"); //$NON-NLS-1$
+ if (fJob != null && fJob.cancel()) {
+ fAnalysisCancelled = true;
+ setAnalysisCompleted();
}
fStarted = false;
}
}
- @Override
- public void close() {
- dispose();
- }
-
@Override
public void dispose() {
super.dispose();
cancel();
}
- private void execute(@NonNull final ITmfTrace trace) {
+ /**
+ * Get an iterable list of all analyzes this analysis depends on. These
+ * analyzes will be scheduled before this analysis starts and the current
+ * analysis will not be considered completed until all the dependent
+ * analyzes are finished.
+ *
+ * @return An iterable list of analysis this analyzes depends on.
+ */
+ protected Iterable<IAnalysisModule> getDependentAnalyses() {
+ return checkNotNull(Collections.EMPTY_LIST);
+ }
+ private void execute(final ITmfTrace trace) {
/*
* TODO: The analysis in a job should be done at the analysis manager
* level instead of depending on this abstract class implementation,
/* Do not execute if analysis has already run */
if (fFinishedLatch.getCount() == 0) {
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "already executed"); //$NON-NLS-1$
return;
}
/* Do not execute if analysis already running */
synchronized (syncObj) {
if (fStarted) {
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "already started, not starting again"); //$NON-NLS-1$
return;
}
fStarted = true;
}
+ /* Execute dependent analyses before creating the job for this one */
+ final Iterable<IAnalysisModule> dependentAnalyses = getDependentAnalyses();
+ for (IAnalysisModule module : dependentAnalyses) {
+ module.schedule();
+ }
+
/*
* Actual analysis will be run on a separate thread
*/
- fJob = new Job(NLS.bind(Messages.TmfAbstractAnalysisModule_RunningAnalysis, getName())) {
+ String jobName = checkNotNull(NLS.bind(Messages.TmfAbstractAnalysisModule_RunningAnalysis, getName()));
+ fJob = new Job(jobName) {
@Override
- protected IStatus run(final IProgressMonitor monitor) {
+ protected @Nullable IStatus run(final @Nullable IProgressMonitor monitor) {
+ IProgressMonitor mon = monitor;
+ if (mon == null) {
+ mon = new NullProgressMonitor();
+ }
try {
- monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+ mon.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
broadcast(new TmfStartAnalysisSignal(TmfAbstractAnalysisModule.this, TmfAbstractAnalysisModule.this));
- fAnalysisCancelled = !executeAnalysis(monitor);
+ TmfCoreTracer.traceAnalysis(TmfAbstractAnalysisModule.this.getId(), TmfAbstractAnalysisModule.this.getTrace(), "started"); //$NON-NLS-1$
+ fAnalysisCancelled = !executeAnalysis(mon);
+ for (IAnalysisModule module : dependentAnalyses) {
+ module.waitForCompletion(mon);
+ }
+ TmfCoreTracer.traceAnalysis(TmfAbstractAnalysisModule.this.getId(), TmfAbstractAnalysisModule.this.getTrace(), "finished"); //$NON-NLS-1$
} catch (TmfAnalysisException e) {
- Activator.logError("Error executing analysis with trace " + getTrace().getName(), e); //$NON-NLS-1$
+ Activator.logError("Error executing analysis with trace " + trace.getName(), e); //$NON-NLS-1$
} finally {
synchronized (syncObj) {
- monitor.done();
+ mon.done();
setAnalysisCompleted();
}
TmfTraceManager.refreshSupplementaryFiles(trace);
@Override
protected void canceling() {
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "job cancelled"); //$NON-NLS-1$
TmfAbstractAnalysisModule.this.canceling();
}
@Override
public IStatus schedule() {
- final ITmfTrace trace = fTrace;
- if (trace == null) {
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, String.format("No trace specified for analysis %s", getName())); //$NON-NLS-1$
+ synchronized (syncObj) {
+ final ITmfTrace trace = getTrace();
+ if (trace == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, String.format("No trace specified for analysis %s", getName())); //$NON-NLS-1$
+ }
+ TmfCoreTracer.traceAnalysis(getId(), getTrace(), "scheduled"); //$NON-NLS-1$
+ execute(trace);
}
- execute(trace);
- return Status.OK_STATUS;
+ return checkNotNull(Status.OK_STATUS);
}
@Override
@TmfSignalHandler
public void traceClosed(TmfTraceClosedSignal signal) {
/* Is the closing trace the one that was requested? */
- if (signal.getTrace() == fTrace) {
- cancel();
- fTrace = null;
+ synchronized (syncObj) {
+ if (signal.getTrace() == fTrace) {
+ cancel();
+ fTrace = null;
+ }
}
}
*
* @param signal
* Trace selected signal
- * @since 3.1
*/
@TmfSignalHandler
public void traceSelected(TmfTraceSelectedSignal signal) {
* @return Full help text for the module
*/
protected String getFullHelpText() {
- return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisModule, getName());
+ return NonNullUtils.nullToEmptyString(NLS.bind(
+ Messages.TmfAbstractAnalysisModule_AnalysisModule,
+ getName()));
}
/**
* @return Short help text describing the module
*/
protected String getShortHelpText(ITmfTrace trace) {
- return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisForTrace, getName(), trace.getName());
+ return NonNullUtils.nullToEmptyString(NLS.bind(
+ Messages.TmfAbstractAnalysisModule_AnalysisForTrace,
+ getName(), trace.getName()));
}
/**
* The trace to apply the analysis to
* @return Help text
*/
- protected String getTraceCannotExecuteHelpText(@NonNull ITmfTrace trace) {
+ protected String getTraceCannotExecuteHelpText(ITmfTrace trace) {
StringBuilder builder = new StringBuilder();
builder.append(NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute, getName()));
for (TmfAnalysisRequirement requirement : getAnalysisRequirements()) {
}
}
}
- return builder.toString();
+ return checkNotNull(builder.toString());
}
@Override
@Override
public String getHelpText(ITmfTrace trace) {
- if (trace == null) {
- return getHelpText();
- }
String text = getShortHelpText(trace);
if (!canExecute(trace)) {
text = text + "\n\n" + getTraceCannotExecuteHelpText(trace); //$NON-NLS-1$
@Override
public Iterable<TmfAnalysisRequirement> getAnalysisRequirements() {
- return Collections.EMPTY_SET;
+ return checkNotNull(Collections.EMPTY_SET);
}
}