package org.eclipse.tracecompass.tmf.core.statesystem;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.tmf.core.statesystem.backends.partial.PartialHistoryBackend;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfExperiment;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceCompleteness;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
/**
* Abstract analysis module to generate a state system. It is a base class that
private static final String EXTENSION = ".ht"; //$NON-NLS-1$
private final CountDownLatch fInitialized = new CountDownLatch(1);
+ private final Object fRequestSyncObj = new Object();
@Nullable private ITmfStateSystemBuilder fStateSystem;
@Nullable private ITmfStateProvider fStateProvider;
@Nullable private IStateHistoryBackend fHtBackend;
@Nullable private ITmfEventRequest fRequest;
+ @Nullable private TmfTimeRange fTimeRange = null;
+
+ private int fNbRead = 0;
/**
* State system backend types
PARTIAL
}
-
/**
* Retrieve a state system belonging to trace, by passing the ID of the
* relevant analysis module.
*/
public static @Nullable ITmfStateSystem getStateSystem(ITmfTrace trace, String moduleId) {
TmfStateSystemAnalysisModule module =
- trace.getAnalysisModuleOfClass(TmfStateSystemAnalysisModule.class, moduleId);
+ TmfTraceUtils.getAnalysisModuleOfClass(trace, TmfStateSystemAnalysisModule.class, moduleId);
if (module != null) {
- module.schedule();
- module.waitForInitialization();
- /*
- * FIXME If we keep a reference to "module", the compiler expects us to
- * close it. The Analysis Module's API should be reworked to not expose
- * these objects directly (utility classes instead?)
- */
- return module.getStateSystem();
+ IStatus status = module.schedule();
+ if (status.isOK()) {
+ module.waitForInitialization();
+ return module.getStateSystem();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieve a state system belonging to trace, by passing the class of the
+ * relevant analysis module. If many modules of the same class exists, the
+ * state system of the first one will be returned.
+ *
+ * This will start the execution of the analysis module, and start the
+ * construction of the state system, if needed.
+ *
+ * @param trace
+ * The trace for which you want the state system
+ * @param clazz
+ * The class of the state system module to retrieve
+ * @return The state system, or null if there was no match
+ */
+ public static @Nullable ITmfStateSystem getStateSystemByModuleClass(ITmfTrace trace, Class<? extends TmfStateSystemAnalysisModule> clazz) {
+ TmfStateSystemAnalysisModule module = null;
+ for (TmfStateSystemAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, clazz)) {
+ module = mod;
+ break;
+ }
+ if (module != null) {
+ IStatus status = module.schedule();
+ if (status.isOK()) {
+ module.waitForInitialization();
+ return module.getStateSystem();
+ }
}
return null;
}
StateSystemBackendType backend = getBackendType();
String directory;
File htFile;
+
+ ITmfTrace trace = getTrace();
+ if (trace == null) {
+ // Analysis was cancelled in the meantime
+ fInitialized.countDown();
+ return false;
+ }
switch (backend) {
case FULL:
- directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
+ directory = TmfTraceManager.getSupplementaryFileDir(trace);
htFile = new File(directory + getSsFileName());
createFullHistory(id, provider, htFile);
break;
case PARTIAL:
- directory = TmfTraceManager.getSupplementaryFileDir(getTrace());
+ directory = TmfTraceManager.getSupplementaryFileDir(trace);
htFile = new File(directory + getSsFileName());
createPartialHistory(id, provider, htFile);
break;
break;
}
} catch (TmfTraceException e) {
+ fInitialized.countDown();
return false;
}
return !mon.isCanceled();
request.cancel();
}
- request = new StateSystemEventRequest(provider);
- provider.getTrace().sendRequest(request);
+ fTimeRange = TmfTimeRange.ETERNITY;
+ final ITmfTrace trace = provider.getTrace();
+ if (trace != null && !isCompleteTrace(trace)) {
+ TmfTimeRange traceTimeRange = trace.getTimeRange();
+ if (traceTimeRange != null) {
+ fTimeRange = traceTimeRange;
+ }
+ }
- /*
- * Only now that we've actually started the build, we'll update the
- * class fields, so that they become visible for other callers.
- */
fStateProvider = provider;
- fRequest = request;
+ synchronized (fRequestSyncObj) {
+ startRequest();
+ }
/*
* The state system object is now created, we can consider this module
* progress monitor displays that it is running).
*/
try {
- request.waitForCompletion();
+ if (fRequest != null) {
+ fRequest.waitForCompletion();
+ }
} catch (InterruptedException e) {
e.printStackTrace();
}
private final ITmfStateProvider sci;
private final ITmfTrace trace;
- public StateSystemEventRequest(ITmfStateProvider sp) {
+ public StateSystemEventRequest(ITmfStateProvider sp, TmfTimeRange timeRange, int index) {
super(sp.getExpectedEventType(),
- TmfTimeRange.ETERNITY,
- 0,
+ timeRange,
+ index,
ITmfEventRequest.ALL_DATA,
ITmfEventRequest.ExecutionType.BACKGROUND);
this.sci = sp;
// sci.getTrace() will eventually return a @NonNull
- @SuppressWarnings("null")
- @NonNull ITmfTrace tr = sci.getTrace();
- trace = tr;
+ trace = checkNotNull(sci.getTrace());
}
@Override
public void handleSuccess() {
super.handleSuccess();
- disposeProvider(false);
+ if (isCompleteTrace(trace)) {
+ disposeProvider(false);
+ } else {
+ fNbRead += getNbRead();
+ synchronized (fRequestSyncObj) {
+ final TmfTimeRange timeRange = fTimeRange;
+ if (timeRange != null) {
+ if (getRange().getEndTime().getValue() < timeRange.getEndTime().getValue()) {
+ startRequest();
+ }
+ }
+ }
+ }
}
@Override
public void handleCancel() {
super.handleCancel();
- disposeProvider(true);
+ if (isCompleteTrace(trace)) {
+ disposeProvider(true);
+ }
}
@Override
@Override
public Iterable<ITmfStateSystem> getStateSystems() {
- @SuppressWarnings("null")
- @NonNull Iterable<ITmfStateSystem> ret = Collections.singleton((ITmfStateSystem) fStateSystem);
- return ret;
+ return checkNotNull(Collections.<ITmfStateSystem> singleton(fStateSystem));
+ }
+
+ /**
+ * Signal handler for the TmfTraceRangeUpdatedSignal signal
+ *
+ * @param signal The incoming signal
+ */
+ @TmfSignalHandler
+ public void traceRangeUpdated(final TmfTraceRangeUpdatedSignal signal) {
+ fTimeRange = signal.getRange();
+ ITmfStateProvider stateProvider = fStateProvider;
+ synchronized (fRequestSyncObj) {
+ if (signal.getTrace() == getTrace() && stateProvider != null && stateProvider.getAssignedStateSystem() != null) {
+ ITmfEventRequest request = fRequest;
+ if ((request == null) || request.isCompleted()) {
+ startRequest();
+ }
+ }
+ }
+ }
+
+ private void startRequest() {
+ ITmfStateProvider stateProvider = fStateProvider;
+ TmfTimeRange timeRange = fTimeRange;
+ if (stateProvider == null || timeRange == null) {
+ return;
+ }
+ ITmfEventRequest request = new StateSystemEventRequest(stateProvider, timeRange, fNbRead);
+ stateProvider.getTrace().sendRequest(request);
+ fRequest = request;
+ }
+
+ private static boolean isCompleteTrace(ITmfTrace trace) {
+ return !(trace instanceof ITmfTraceCompleteness) || ((ITmfTraceCompleteness) trace).isComplete();
}
}